クエリは次のように機能します:
SELECT a.*
FROM article a
LEFT JOIN (
SELECT DISTINCT ON (article_id)
article_id, value
FROM metrics m
WHERE name = 'score'
ORDER BY article_id, date_created DESC
) m ON m.metrics_id = a.metrics_id
ORDER BY m.value DESC;
最初 、「最新の」value
を取得します name = 'score'
の場合 サブクエリm
の記事ごと 。この関連する回答で使用されている手法の詳細:
しかし、あなたは非常に基本的な誤解の犠牲になっているようです:
「自然な秩序」はありません テーブルで。 SELECT
で 、ORDER BY
する必要があります 明確に定義された基準。このクエリの目的のために、列metrics.date_created
を想定しています。 。そのようなものがない場合は、方法がありません 「最新」を定義し、複数の修飾行からの任意の選択にフォールバックすることを余儀なくされます:
ORDER BY article_id
これはではありません 信頼性のある。 Postgresは選択した行を選択します。テーブルの更新またはクエリプランの変更により変更される可能性があります。
次へ 、LEFT JOIN
テーブルarticle
へ およびORDER BY value
。 NULL
最後に並べ替えられるため、修飾値のない記事が最後になります。
注:一部のそれほどスマートではないORM(RubyのActiveRecordはその1つであると思います)は、説明的でなく、特徴のない id
を使用します。 主キーの名前として。指定しなかった実際の列名に合わせる必要があります。
パフォーマンス
まともなはずです。 Postgresに関する限り、これは「単純な」クエリです。テーブルmetrics
の部分的な複数列のインデックス 速くなります:
CREATE INDEX metrics_some_name_idx ON metrics(article_id, date_created)
WHERE name = 'score';
この順序の列。 PostgreSQL 9.2+では、列の値を追加して、インデックスのみのスキャンを可能にすることができます。
CREATE INDEX metrics_some_name_idx ON metrics(article_id, date_created, value)
WHERE name = 'score';