Rails,Count和Group

时间:2010-09-05 23:40:44

标签: ruby-on-rails ruby postgresql

我有一张表:

 +--------+-----------+-------+-----------+
 |house_no|house_alpha|flat_no|street_name|
 +--------+-----------+-------+-----------+
 |       1|           |       |James St   |
 |       1|           |       |James St   |
 |       1|           |       |James St   |
 |       2|          A|       |James St   |
 |       2|          B|       |James St   |
 |       3|          A|       |James St   |
 |       4|           |    416|James St   |
 |       4|           |    416|James St   |
 +--------+-----------+-------+-----------+

我正在尝试计算此表中不同地址的数量。 这将返回不同的地址:

Address.all(:select => 'street_name, flat_no, house_no, house_alpha',
            :group => 'street_name, flat_no, house_no, house_alpha').length

但我想在SQL端做到这一点。并试图结合计数和小组不喜欢我。我显然做错了什么。

(数据库是postgres,rails是2.x)。

3 个答案:

答案 0 :(得分:6)

对于带有Arel的rails 3,您可以执行以下操作:

Address.group(:street_name, :flat_no, :house_no, :house_alpha).having("count(*) > 0").count.size

答案 1 :(得分:2)

我不确定是否有一种漂亮的Rails方法可以跨分组列进行计数。在SQL中有很多奇怪的方法可以做到这一点,但这种方式很容易理解。

Address.find(:all, 
             :select => "count(*) as addr_count", 
             :having => "addr_count > 0", 
             :group => 'street_name, flat_no, house_no, house_alpha').size

这将运行以下SQL查询。

SELECT count(*) as addr_count FROM "addresses" GROUP BY street_name, flat_no, house_no, house_alpha HAVING addr_count > 0

编辑:请阅读Postgres

从下面的评论中,以下是在Postgres上执行上述操作的方法。

Address.find(:all, 
             :select => "count(*)", 
             :having => "count(*) > 0", 
             :group => 'street_name, flat_no, house_no, house_alpha').size

这将生成以下查询。

SELECT count(*) FROM "addresses" GROUP BY street_name, flat_no, house_no, house_alpha HAVING count(*) > 0

答案 2 :(得分:1)

Rails 2 中,我发现:group选项不能正常运行(在我最新的情况下,它创建了一个只包含每组中第一条记录的数组)。作为替代方案,您可以将数据库搜索与EnumerableArray#group_by结合使用,如下所示:

addresses = Address.find(:all, 
             :select => "count(*) as addr_count", 
             :having => "addr_count > 0"), 
grouped_addrs = addresses.group_by{|a| [a.street_name, a.flat_no, a.house_no, a.house_alpha] }