2 つのテーブルがcharts
ありchart_entries
、現在の上位 5 つのチャート位置を取得したいと考えています (chart_entries
特定の位置で最新のものを選択することに基づいて)。
これを単一のクエリにする方法はありますか? 理想的には、私のチャートには最大 500 のポジションがあるので、このような複数のクエリを持つことは現実的ではありません。
レールでは、現在このメソッドを使用していますChart.rb
def table
(1..5).each do |i|
chart_entries.where(position: i).order('entered_at DESC').first
end
end
次のSQLを生成します
SELECT "chart_entries".* FROM "chart_entries" WHERE "chart_entries"."chart_id" = 1 AND "chart_entries"."position" = 1 ORDER BY entered_at DESC LIMIT 1
SELECT "chart_entries".* FROM "chart_entries" WHERE "chart_entries"."chart_id" = 1 AND "chart_entries"."position" = 2 ORDER BY entered_at DESC LIMIT 1
SELECT "chart_entries".* FROM "chart_entries" WHERE "chart_entries"."chart_id" = 1 AND "chart_entries"."position" = 3 ORDER BY entered_at DESC LIMIT 1
SELECT "chart_entries".* FROM "chart_entries" WHERE "chart_entries"."chart_id" = 1 AND "chart_entries"."position" = 4 ORDER BY entered_at DESC LIMIT 1
SELECT "chart_entries".* FROM "chart_entries" WHERE "chart_entries"."chart_id" = 1 AND "chart_entries"."position" = 5 ORDER BY entered_at DESC LIMIT 1
これはテーブル構造です (postgresql)
CREATE TABLE chart_entries (
id integer NOT NULL,
chart_id integer,
entity_id integer,
"position" integer,
entered_at timestamp without time zone,
locale character varying(255)
);
CREATE TABLE charts (
id integer NOT NULL,
name character varying(255)
);
これが私の最終的な解決策でした
chart_entries.where(position: [1..5]).group('position, id').having('entered_at = MAX(entered_at)').order('position ASC')