通过单个表上的查询在组中汇总

时间:2012-04-01 16:46:55

标签: ruby-on-rails ruby-on-rails-3 activerecord count group-by

我有一个任务模型,其中包含created_at,hours和不同状态等属性,我希望按月汇总,并总结不同的状态。

| Month   | Count | Hours | States
| 2012-01 | 22    | 26.5  | new(3), closed(4), others(15)
| 2012-02 | 12    | 16.5  | new(0), approved(2), closed(9), others(1)
...

目前我正在使用此查询按月分组并给我数+小时。

@tasks = Task.select("date(created_at), count(id), sum(hours) AS hours")
             .group("MONTH(created_at)") 
             .order('created_at')

如何在所有不同状态下添加总和?

我已经阅读过有关group_by的内容,但我认为这并不是很好的结果。

更新

通过这样的查询,我几乎得到了我想要的东西。

@tasks = Tasks.select("date(created_at), state, count(state), sum(hours) AS hours")
          .group("MONTH(created_at)") 
          .group("state")
          .order('created_at')

| Month   | Count | Hours | State
| 2012-01 | 3     | 26.5  | new
| 2012-01 | 4     | 16.5  | approved
| 2012-01 | 15    | 22.5  | others
| 2012-02 | 2     | 16.5  | approved
| 2012-02 | 9     | 16.5  | closed
...

UPDATE2

我有一个SQL查询,它给了我需要的结果。

@tasks = Task.select("
  DATE( created_at ) AS month, 
  COUNT( state ), 
  SUM( hours ) AS hours,
  COUNT( case when `state` = 'new' then `state` else NULL end ) AS state_new,
  SUM( case when `state` = 'new' then `hours` else NULL end ) AS state_new_hours,
  COUNT( case when `state` = 'approved' then `state` else NULL end ) AS state_approved,
  SUM( case when `state` = 'approved' then `hours` else NULL end ) AS state_approved_hours,
  COUNT( case when `state` = 'closed' then `state` else NULL end ) AS state_closed,
  SUM( case when `state` = 'closed' then `hours` else NULL end ) AS state_closed_hours,
  COUNT( case when `state` != 'new' AND `state` != 'approved' AND `state` != 'closed' then `state` else NULL end ) AS state_misc")
.group("MONTH(created_at)") 
.order('created_at')

这可以通过加入完成吗?如何在更常见的rails方式中使用动态状态?

1 个答案:

答案 0 :(得分:1)

所以,我假设您正在使用MySQL并且您有一个单独的states表,其他列中的状态由ID引用,如下所示:

| ID | Name   |
| 1  | new    |
| 2  | closed |
| 3  | open   |

所以在MySQL中执行这个SQL语句

SELECT states.name AS state, DATE_FORMAT(tasks.created_at, '%Y-%m') AS month,
       COUNT(tasks.id) AS count, SUM(tasks.hours) AS hours
  FROM states JOIN tasks ON states.id = tasks.state_id
GROUP BY state, month
ORDER BY month

你应该得到这样的结果

| state  | month   | count | hours |
| open   | 2012-03 | 22    | 38.5  |
| open   | 2012-04 | 17    | 40.0  |
| closed | 2012-03 | 45    | 0.5   |

因此,您只需将此查询带入ActiveRelation查询,或者您可以使用Task.find_by_sql。 这与描述你希望结果看起来的方式不完全相同,但是使用这个集合你可以在执行后使用普通红宝石改变它......