2

最近コメントされた記事を選択する必要があります。各記事の最後のコメント、つまり次を含む行の他の列ですmax(c.created)

SELECT a.id, a.title, a.text, max(c.created) AS cid, c.text?
FROM subscriptions s
JOIN articles a ON a.id=s.article_id
JOIN comments c ON c.article_id=a.id
WHERE s.user_id=%d
GROUP BY a.id, a.title, a.text
ORDER BY max(c.created) DESC LIMIT 10;

Postgres は、c.text を GROUP BY に入れる必要があると教えてくれます。明らかに、私はこれをしたくありません。最小/最大も適合しません。これを選択する方法がわかりません。

ご意見をお聞かせください。

4

1 に答える 1

2

PostgreSQL では、DISTINCT ONおそらくこの種のクエリに最適なソリューションです。

SELECT DISTINCT ON (a.id)
       a.id, a.title, a.text, c.created, c.text
FROM   subscriptions s
JOIN   articles      a ON a.id = s.article_id
JOIN   comments      c ON c.article_id = a.id
WHERE  s.user_id = %d
ORDER  BY a.id, c.created DESC

これにより、最新のコメントと関連する追加の列を含む記事が取得されます。この密接に関連する回答
の説明、リンク、およびベンチマーク。

最新の 10 件を取得するには、これをサブクエリでラップします。

SELECT *
FROM  (
    SELECT DISTINCT ON (a.id)
             a.id, a.title, a.text, c.created, c.text
    FROM   subscriptions s
    JOIN   articles      a ON a.id = s.article_id
    JOIN   comments      c ON c.article_id = a.id
    WHERE  s.user_id = 12
    ORDER  BY a.id, c.created DESC
    ) x
ORDER  BY created DESC
LIMIT  10;

または、ウィンドウ関数を standard と組み合わせて使用​​できますDISTINCT

SELECT DISTINCT
       a.id, a.title, a.text, c.created, c.text
      ,first_value(c.created) OVER w AS c_created
      ,first_value(c.text)    OVER w AS c_text
FROM   subscriptions s
JOIN   articles      a ON a.id = s.article_id
JOIN   comments      c ON c.article_id = a.id
WHERE  s.user_id = 12
WINDOW w AS (PARTITION BY c.article_id ORDER BY c.created DESC)
ORDER  BY c_created DESC
LIMIT  10;

DISTINCT(集約関数とは異なり)afterウィンドウ関数が適用されるため、これは機能します。
どちらが速いかをテストする必要があります。最後の方が遅いと思います。

于 2012-11-13T23:54:58.857 に答える