1

ここで同様の質問をすべて読みましたが、グループ内で制限を行う方法がわかりません。PSQL doc を読んでも役に立ちませんでした:(次のことを考慮してください。

CREATE TABLE article_relationship
(
    article_from INT NOT NULL,
    article_to INT NOT NULL,
    score INT
);

特定の記事 ID ごとに上位 5 件の関連記事のリストをスコアで並べ替えて取得したいと考えています。

これが私が試したものです:

select DISTINCT o.article_from
from article_relationship o
join lateral (
       select i.article_from, i.article_to, i.score from article_relationship i
       order by score desc
       limit 5
       ) p on p.article_from = o.article_from
where o.article_from IN (18329382, 61913904, 66538293, 66540477, 66496909)
order by o.article_from;

そして、それは何も返しません。外側のクエリはループのようなものだという印象を受けていたので、そこにはソース ID だけが必要だと思います。

articlesまた、列があるテーブルに参加して、関連記事のタイトルを結果セットに取得しidたい場合はどうすればよいですか?title

内部クエリに結合を追加しました:

select o.id, p.*
from articles o
join lateral (
       select a.title, i.article_from, i.article_to, i.score
       from article_relationship i
       INNER JOIN articles a on a.id = i.article_to
       where i.article_from = o.id
       order by score desc
       limit 5
       ) p on true
where o.id IN (18329382, 61913904, 66538293, 66540477, 66496909)
order by o.id;

しかし、それはそれを非常に遅くしました。

4

2 に答える 2

1

クエリから行が返されない問題は、結合条件が間違っていることですON p.article_from = o.article_from。これは明らかにそうあるべきON p.article_from = o.article_toです。

その問題はさておき、クエリは記事 ID ごとに上位 5 つのスコア関係を返しません。代わりに、テーブル全体で上位 5 つの参照記事の 1 つを参照する記事 ID と、(また) ID を指定した 5 つの参照記事のうち少なくとも 1 つを参照する記事 ID を返します。

サブ選択でスコアをランク付けするウィンドウ関数を使用して、参照記事ごとに上位 5 つの評価された参照記事を取得し、メイン クエリで上位 5 つだけを選択できます。参照記事 ID のリストを指定することは、参照記事ごとにこれらの参照記事がどのようにスコア付けされるかを効果的にランク付けすることを意味します。

SELECT article_from, article_to, score
FROM (
    SELECT article_from, article_to, score, 
           rank() OVER (PARTITION BY article_from ORDER BY score DESC) AS rnk
    FROM article_relationship
    WHERE article_to IN (18329382, 61913904, 66538293, 66540477, 66496909) ) a
WHERE rnk < 6
ORDER BY article_from, score DESC;

これは、コードごとに最大 5 つのレコードを返すという点でコードとは異なりますarticle_fromが、最初の説明と一致しています。

テーブルからの列の追加articlesは、メイン クエリで簡単に実行できます。

SELECT a.article_from, a.article_to, a.score, articles.*
FROM (
    SELECT article_from, article_to, score, 
           rank() OVER (PARTITION BY article_from ORDER BY score DESC) AS rnk
    FROM article_relationship
    WHERE article_to IN (18329382, 61913904, 66538293, 66540477, 66496909) ) a
JOIN articles ON articles.id = a.article_to
WHERE a.rnk < 6
ORDER BY a.article_from, a.score DESC;
于 2016-12-22T06:44:32.570 に答える