2016-10-19 7 views
2

私のRailsアプリケーションでは、ユーザーはイベントに「投票」することができます。いくつかのイベントは特定の日付のみであり、いくつかのイベントは進行中です。 Rails&ActiveRecord:難しいSQLクエリ

は、私はどちらかA)ユーザーが がないOR B)ユーザーがヶ月以上前に投票した継続的なイベントに投票しているすべてのイベントをレンダリングするクエリを作成しようとしています。

イベントには、「進行中」のブール型列があります。イベントhas_many vote。そしてユーザーhas_many票。

ユーザーが持っているすべてのイベントを取得するクエリです。は、が投票しました。できます。

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") 
    } 

私は、クエリのまたは一部を追加しようとしています。私はユーザーが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 OR events.ongoing = ? AND MAX(votes.created_at) < ?", true, 1.month.ago 
     ) 
    } 

しかし、これは私にエラーを与えている:

PG::GroupingError: ERROR: aggregate functions are not allowed in 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") 
    } 

しかし、これは私にエラー与えている:

ERROR: column must appear in the GROUP BY clause or be used in an aggregate function

私が見ている適切なクエリは何ですかのためにing?

+0

を行うことができますし、それらをタグ付けするようにしてくださいRDBMSを作成し、テーブルと期待される結果の良い例を作成します。 Ruby-on-Railsよりもpostgresとmysqlタグの方がはるかに多く、より良い回答を得る傾向があります。 – max

+0

MAXを使用する目的は何ですか?一致したレコードから最新のレコードを取得するか、レコードを新規レコードから古いレコードに並べ替えるだけですか? – YTorii

+0

@YTorii 1か月以上前に作成されたかどうかを調べるには、一致するレコードから最新のものを取得する必要があります –

答えて

0

EDIT: HAVINGでORを書く方法がないようです。サブクエリ(Using 'OR' between HAVING and WHERE clause in MySQL?)またはUNIONを使用してこれを解決できます。

これを2つのクエリに分けることができます。

のみActiveRecordのソリューション:https://stackoverflow.com/a/15413611/5213979

+0

Hmmm .. 1ヶ月前の投票ですべてのイベントが返されるため、これが機能するかどうかはわかりません。しかし、私は最近の投票が1ヶ月前に行われたイベントを返すだけです –

+0

@JacksonCunningham Ok、それを実現しました。 –

+0

2つのクエリでこれを行う例を挙げることはできますか?私はこのアプローチが気に入っていますが、 "OR" –

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') 
} 

を試すことができ、その後、あなたの方法では、あなたが複雑なSQLの質問について

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

関連する問題