新手问题 [已解决] 求教统计实现方法

chairy11 · 2014年10月14日 · 最后由 chairy11 回复于 2014年10月14日 · 2113 次阅读

问题

一时还不知道应该怎么去google这个问题,先发帖来问问思路哈~

目标结果是一个统计工作量的表,多个用户对应多个项目的工作量,如下图:

在model里面,我是用一个workload表的,有user_id, project_id。 user has_many workloads, project has_many workloads。 现在这个统计表的话,它是要确定对应着每个项目每个人的工作量。那就是双维度的确定,既要是这个project,又要正好是这个user。 一般大家是怎么做的?难道要先来个二维数组?workload[project][user]什么的?

解决方案

controller中

def fetch_workloads_data(pws)
  workloads_table = Hash.new(0)
  pws.each do |pw|
    pw.workloads.each do |wl|
      workloads_table[[wl.project_id, pw.user_id]] += wl.day_count
    end
  end
  return workloads_table
end

view中



<% @projects.each do |project|  %>
 <tr>
   <td><%= "#{project.name}-#{project.id}" %></td>
   <% @users.each do |user| %>
     <td><%= @workloads_table[[project.id, user.id]] %></td>
   <% end %>
 </tr>
 <% end %>

暂时的解决方案是:

  1. 做了一个hash表,本来想做个二维hash的,不知道为什么总报错,只好最后用一个array来做键,这个array为[project_id, user_id]
  2. hash默认value值为0
  3. 在view中用hash提取出结果放进td。
共收到 15 条回复
class User < ActiveRecord::Base
  has_many :workloads
end

class Project < ActiveRecord::Base
  has_many :workloads
end

class Workload < ActiveRecord::Base
  belongs_to :user
  belongs_to :project

  // 工作量放这个表里面
end

另外google的方法: http://lmgtfy.com/?q=how+to+set+many+to+many+rails

#1楼 @MrPasserby 我的model结构和你是一样的。但我现在不知道怎么写的是这个统计的方法。 以前我们做列表,都是在一行中把相应的attributes一一列出来,比如说user表,有name, tel, address,直接就是user.name, user.tel, user.address,列就出来了。 可是我现在想要1个attribute,但它是由两个参数确定的,一是user, 另一个是project,要恰好对应对这个表格中,如果没有,就显示为0.

啊……好像我表达不清……

反正就是,想要的结果是那个图,多个项目多个用户对应的工作量的统计……

额,这不是数据库多对多的关系么? 把这个 attribute 加到 workloads 这个表里,在 Workload 这个 model 里加统计方法就好了。

#3楼 @kungs 呜呜呜,还是不懂……我这还有其它嵌套的,所以没有给workload建controller。我会在别的controller里提取。问题是,controller的方法怎么写,view怎么写?

我感绝大概最直观的做法会是这个样子地:

Project.all.each do |p|
  users = p. workloads.select("user_id, count(user_id)").group("user_id")
end

不知道是不是楼主说的在controller中的取法

#5楼 @dn365 Yes,你对我的问题的理解方向对了。 但是这样的, 再细化一点,是统计每周的每个人在每个项目上的工作量分布。 workload表里面有day_count字段,这个才是工作量,然后有user_id, project_id。

但我对你的解决方案还不太理解,我想想,你这个count(user_id)是指这个用户出现的次数累加吗? 我再想想……

这是简单的多维报表,或交叉报表。如果出很多这样的报表,就不y考要虑写代码了,找一个报表工具/多维分析引擎。

#7楼 @wushexu 暂时还不是很多。能能代码写吗?报表工具、多维分析引擎是什么?那个wice_grid算吗?

#6楼 @chairy11 哦,之前不知道workload表设计有day_count字段,误理解为统计user_id数了 按楼主的需求再该一下估计能实现

Project.all.each do |p|
  #weeks array 按周划分时间段
  weeks = [["begin_time","end_time"]]
  weeks.each do |week|
    users = p. workloads.select("user_id, sum(day_count)").where(["created_at >= ? created_at < ?"]+ week).group("user_id")
  end
end

比较丑陋,只是实现楼主所需功能

#8楼 @chairy11 我在 https://www.ruby-toolbox.com/categories/reporting.html 下浏览了下,遗憾的好像没有合适的报表工具。多维分析引擎即OLAP引擎,Ruby更没有了。 实现一个基本的通用多维报表组件也并不难。

workload这个表好像就是你要的统计数据吧

实现通用(多维)报表组件的要点是,要把model、model关联忘掉。

假设数据有A B C D V列,A B C D是维度(Dimension),V是数值列(Measure) 报表的行上显示 A B(A列有合并单元格),列上显示C 记dimensions=[A,B,C,D,V],layout=[[A,B],[C]]

查出数据:sleect A,B,C,sum(V) from T group by A,B,C,按维度列分组,对数值列做聚集运算(如sum)

转换成内存表示:{ [a1,b1]=>{c1=>v11,c2=>v22}, [a1,b2]=>{c1=>v21,c2=>v22}, [a2,b1]=>{c1=>v31,c2=>v32}, } 这是根据dimensions和layout自动生成的,是一般化的。这只是其中一种表示。

生成表格:A,B取值有多少组合就要多少行,C有多少取值就有多少列 如果行或列上有多个维度,生成表格时要处理合并单元格,设置TD/TH的rowspan或colspan的值

#12楼 @wushexu 呜呜呜,好深奥……有github上哪个项目有类似的代码吗?给我参考一下下……

#9楼 @dn365 好的,谢谢,我先试试……

#1楼 @MrPasserby #3楼 @kungs #5楼 @dn365 #12楼 @wushexu #11楼 @liujianhei 暂时用hash解决了,以后再慢慢留意更优化的方案吧。 谢谢各位哈~

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册