4

以下をアクティブレコードクエリに変換するにはどうすればよいですか?

SELECT reviews.style_id, AVG("col1"), AVG("col2")
  FROM reviews, audios
 WHERE reviews.consumer_id = audios.consumer_id
 GROUP BY style_id;

col1col2はaudiosテーブルに属していますが、一意の名前が付けられているため(に類似した列名reviewsがないため)、あいまいなエラーは発生しません。

私はPostgreSQLを使用しています。

4

1 に答える 1

8

Reviewとの間に関連付けがある場合は、次のAudioようになります。

revs = Review.joins(:audios)
             .group('style_id')
             .select('style_id, avg(col1) as avg_col1, avg(col2) as avg_col2')

Reviewこれにより、のインスタンスのリストが表示されrevs、それらのインスタンスには、平均にアクセスするための追加avg_col1のメソッドと通常の/メソッドがありますが、通常提供される他の列アクセサーメソッドでは例外が発生します。avg_col2stylestyle_idReview

アソシエーションを設定していない場合は、手動でJOINを実行できます。

revs = Review.joins('join audios on reviews.consumer_id = audios.consumer_id')
             .group('style_id')
             .select('style_id, avg(col1) as avg_col1, avg(col2) as avg_col2')

必要なのがすべてのActiveRecordラッピングとオーバーヘッドのない生データだけである場合は、生のSQLを実行し、次を使用して手動でハッシュ化できますselect_rows

Review.connection.select_rows(%q{
    select r.style_id, avg(a.col1), avg(a.col2')
    from reviews r
    join audios  a on r.consumer_id = a.consumer_id
    group by r.style_id
}).map do
  { :style_id => r.shift, :avg_col1 => r.shift.to_f, :avg_col2 => r.shift.to_f }
end

それはあなたにハッシュの配列を与えるでしょう。Struct単純なデータラッパークラスを作成するために使用して、そのアプローチを単純化することもできます。

c    = Struct.new(:style_id, :avg_col1, :avg_col2)
revs = Review.connection.select_rows(%q{...}).map do |r|
  c.new(r.shift, r.shift.to_f, r.shift.to_f)
end

PS:SQLで暗黙的な結合条件を使用しないでください。これは、外積を生成するための迅速で簡単な方法です。明示的な結合条件を使用してください。

SELECT ...
  FROM reviews JOIN audios ON reviews.consumer_id = audios.consumer_id
 GROUP BY style_id
于 2012-05-17T16:45:22.873 に答える