Rails& ActiveRecord:困难的SQL查询

时间:2016-10-19 23:35:44

标签: ruby-on-rails activerecord

在我的Rails应用程序中,我允许用户"投票"关于事件。有些活动只是一个特定日期,有些活动正在进行中。

我正在尝试构建一个查询,该查询呈现A)用户上投票的所有事件或 B)用户投票的正在进行的事件 over 1个月前。

活动有"正在进行"布尔列。活动有很多票。而且用户有很多票。

这是我的查询,以获取用户投票的所有事件。它有效。

scope :unvoted, ->(user_id) {
    joins(
         "LEFT OUTER JOIN votes ON votes.event_id = events.id AND " +
         "votes.user_id = #{user_id}"
         ).where("votes.id IS NULL")
    }

我正在尝试添加查询的部分。我需要包括"正在进行的"用户在一个月前投票的事件。这就是我的尝试:

scope :unvoted, ->(user_id) {
    joins(
          "LEFT OUTER JOIN votes ON votes.event_id = events.id AND " +
          "votes.user_id = #{user_id}"
         )
         .where(
                 "votes.id IS NULL OR events.ongoing = ? AND MAX(votes.created_at) < ?", true, 1.month.ago
          )
  }

但是这给了我错误:

  

PG :: GroupingError:错误:WHERE

中不允许使用聚合函数

所以我尝试了这个:

scope :unvoted, ->(user_id) {
    joins(
          "LEFT OUTER JOIN votes ON votes.event_id = events.id AND " +
          "votes.user_id = #{user_id}"
                            ).
   having('votes.id IS NULL OR events.ongoing = ? AND MAX("votes"."created_at") < ?', true, 1.month.ago).
   group("events.id")
  }

但是这给了我错误:

  

错误:列必须出现在GROUP BY子句中或用于聚合函数

我正在寻找的正确查询是什么?

2 个答案:

答案 0 :(得分:0)

修改 似乎没有办法用HAVING写OR。您可以使用子查询(Using 'OR' between HAVING and WHERE clause in MySQL?)或UNION来解决此问题。

或者为了简单起见,您可以将其分解为两个查询。

仅限ActiveRecord解决方案:https://stackoverflow.com/a/15413611/5213979

答案 1 :(得分:0)

你能试试吗

scope :unvoted, ->(user_id) {
    joins(
      "LEFT OUTER JOIN votes ON votes.event_id = events.id AND " +
      "votes.user_id = #{user_id}"
    ).where(
      "votes.id IS NULL OR events.ongoing = ?", true                      
    ).select('events.*, MAX(votes.created_at) as created_at')
    ).group('events.id')
}

然后在你的方法中,你可以做到

Event.unvoted.select{|e| e.created_at < 1.month.ago}