按年,月和组分组然后计入ActiveRecord 3

时间:2011-12-12 04:24:13

标签: sql ruby-on-rails ruby activerecord

我正在尝试计算在一年和一个月内创建的所有用户的数量,但以下似乎没有按预期工作。

User.group("YEAR(created_AT), MONTH(created_at)").
     count("DISTINCT(id), YEAR(created_at), MONTH(created_at)")

我正在寻找像

这样的东西
{2011 => {1 => 222, 2 => 333, 4 => 444, 5 => 667 ... }}

但我正在

{1 => 222, 2 => 333, 4 => 444, 5 => 667 ... }

我错过了什么,或者ActiveRecord在一次查询中不能给我这个结果?

1 个答案:

答案 0 :(得分:14)

count方法不像您认为的那样有效。你最终这样做了:

select count(distinct(id), year(created_at), month(created_at))
from users
group by year(created_at), month(created_at)

那个SELECT子句非常狡猾,但MySQL会以通常的草率方式让它通过。我想你想要这个查询:

select count(distinct(id)), year(created_at), month(created_at)
from users
group by year(created_at), month(created_at)

我可能会像这样直接select_all

a = User.connection.select_all(%q{
    select count(distinct(id)) as c, year(created_at) as y, month(created_at) as m
    from users
    group by y, m
})

或者你可以这样做:

a = User.connection.select_all(
    User.select('count(distinct(id)) as c, year(created_at) as y, month(created_at) as m').
         group('y, m')
)

这些将为您提供一个数组,a,其中包含cym这样的键:

a = [
    { 'c' => '23', 'y' => '2010', 'm' => '11' },
    { 'c' => '1',  'y' => '2011', 'm' =>  '1' },
    { 'c' => '5',  'y' => '2011', 'm' =>  '3' },
    { 'c' => '2',  'y' => '2011', 'm' =>  '4' },
    { 'c' => '11', 'y' => '2011', 'm' =>  '8' }
]

然后,您需要完成一些数据争论:

h = a.group_by { |x| x['y'] }.each_with_object({}) do |(y,v), h|
    h[y.to_i] = Hash[v.map { |e| [e['m'].to_i, e['c'].to_i] }]
end
# {2010 => {11 => 23}, 2011 => {1 => 1, 3 => 5, 4 => 2, 8 => 11}}