【问题标题】:Rails/ActiveRecord: Can I perform this query without passing the SQL string to #order?Rails/ActiveRecord:我可以在不将 SQL 字符串传递给#order 的情况下执行此查询吗?
【发布时间】:2019-02-15 21:44:28
【问题描述】:

我有两个型号 IssueLabel。他们有一个多对多的关系。

我有一个方法可以返回指向最多问题的十个标签。

class Label < ApplicationRecord
  has_many :tags
  has_many :issues, through: :tags

    def self.top
        Label.joins(:issues)
        .group(:name)
        .order('count_id desc')
        .count(:id)
        .take(10)
    end
end

它完全符合我的预期,但我想知道是否可以在没有 SQL 字符串的情况下编写查询。

order('count_id DESC') 让我很困惑。 count_id 来自哪里?没有名为 count_id 的列。

Label.joins(:issues).group(:name).column_names
#=> ["id", "name", "created_at", "updated_at"]

我找到了一些 SQL 示例 here。我觉得和ORDER BY COUNT(Id)基本一样:

SELECT COUNT(Id), Country
FROM Customer
GROUP BY Country
ORDER BY COUNT(Id) DESC

是否可以在不传入 SQL 字符串的情况下执行相同的查询?单独使用ActiveRecord查询接口可以吗?

【问题讨论】:

    标签: sql ruby-on-rails activerecord rails-activerecord


    【解决方案1】:

    如果您查看查询日志,您会看到如下内容:

    select count(labels.id) as count_id ...
    

    group 调用(带有任何参数)和count(:id) 调用的组合使 ActiveRecord 将count_id 列别名添加到查询中。我认为这在任何地方都没有记录或指定(至少我能找到),但如果你有足够的勇气浏览 Active Record 源,你可以看到它发生。

    一般来说,如果你添加一个 GROUP BY 然后 count(:x),Active Record 将添加一个 count_x 别名。没有此列,因此您不能说 order(:count_id)order(count_id: :desc) 或任何其他常见的非字符串替代品。 AFAIK,您必须使用字符串,但您可以将其包装在 Arel.sql 中以防止将来出现弃用问题:

    Label.joins(:issues)
         .group(:name)
         .order(Arel.sql('count_id desc'))
         .count(:id)
         .take(10)
    

    对此无法保证,因此如果您使用它,您应该在测试套件中包含一些内容,以便在将来行为发生变化时发现任何问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-18
      • 1970-01-01
      • 2021-05-29
      • 1970-01-01
      相关资源
      最近更新 更多