【问题标题】:ActiveRecord condition with count less than for association计数小于关联的 ActiveRecord 条件
【发布时间】:2012-11-28 19:01:14
【问题描述】:

我有一个User 那个has_many messages。 我需要创建一个查询

'Get me all users who's (message.opened == false) count < 3'

现在,我正在使用User.all,遍历所有用户,并手动计数。我知道这不是很有效,并且可以在一个查询中完成,但是我是 SQL/ActiveRecord 的新手,所以在这里需要一些帮助。 谢谢

【问题讨论】:

  • count 是你模型中的属性吗?我不明白你真正需要什么?所有 message.opened == false 的用户?这里 count 的目的是什么?你能解释一下你需要的查询吗

标签: sql ruby-on-rails ruby activerecord


【解决方案1】:

假设 Rails 3 语法。您可以执行以下操作:

User.joins(:messages).where(:messages => {:opened => false}).group(:user_id).having("COUNT(messages.id) < 3)

【讨论】:

    【解决方案2】:

    这应该可行:

    User.includes(:messages).group("users.id").where("messages.opened = 0").having("count(messages.id) < 3")
    

    这将创建两个查询,一个用于分组查询,一个用于通过连接预先加载结果用户和消息。

    【讨论】:

      【解决方案3】:

      这里是您的问题的解决方案

      User.includes(:messages).group("users.id").where("messages.opened = 0").having("count(messages.id) < 3")
      

      但你还能做的就是为此创建一个范围

      scope :not_opened_less_three_count, includes(:messages).group("users.id").where("messages.opened = 0").having("count(messages.id) < 3")
      

      然后你可以在任何你需要的地方使用它

      User.not_opened_less_three_count
      

      【讨论】:

      • 不确定何时更改,但在 Rails 5(可能是 Rails 4.x)中,您应该使用 eager_load 代替 includes
      【解决方案4】:

      试试这个

      User.includes(:messages).group('users.id').having('SUM(IFNULL(messages.opened = 0, 1)) < 3')
      

      它至少适用于 MySQL,AND 假设您的布尔值 true 在数据库中为 1。

      编辑我已经颠倒了条件

      PS IFNULL 是否可以处理 messages.opened 可以是 NULL

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-06
        • 1970-01-01
        相关资源
        最近更新 更多