【问题标题】:Rails, Count and GroupRails,计数和组
【发布时间】:2011-04-08 13:50:10
【问题描述】:

我有一张这样的桌子:

 +--------+-----------+-------+-----------+
 |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)。

【问题讨论】:

  • 你的意思是Address.count(:group => 'street_name, flat_no, house_no, house_alpha', :distinct => true)不起作用?

标签: ruby-on-rails ruby postgresql


【解决方案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] }

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      我不确定是否有一种漂亮的 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 阅读本文

      从下面的 cmets 来看,这是在 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
      

      【讨论】:

      • addr_count 是个神奇的东西吗?还是我需要为此添加一列?你写的不行。
      • addr_count 只是一个 SQL 别名,没有什么神奇之处。它不代表一列。请发布您的控制台输出和日志,以解释“不起作用”的含义。
      • 另外,你的表有没有 id 列?
      • 您不能在 HAVING 中使用列别名 - 您需要重复 count() 表达式,使其“... HAVING count() > 0” .有可能只是在 :have 规范中更改它 - 我不知道 rails 所以我不能评论那部分。
      • @Magnus 这是 postgres 的东西吗?我发布的代码绝对适用于 sqlite3。
      猜你喜欢
      • 2011-01-02
      • 1970-01-01
      • 2013-12-12
      • 1970-01-01
      • 2017-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多