虽然我在这里阅读了所有类似的问题,但我无法弄清楚如何限制群体。阅读PSQL文档也没有帮助:(考虑以下内容:
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;
但是它非常慢。
答案 0 :(得分:1)
从查询中返回没有行的问题是您的连接条件错误:ON p.article_from = o.article_from
;这显然应该是ON p.article_from = o.article_to
。
除了这个问题,你的查询不会返回每篇文章ID的前5个得分关系;相反,它将返回引用整个表中5个最高评级引用文章之一的文章ID,以及(同时)为您指定id的5个引用文章中的至少1个。
您可以使用窗口函数获取每个引用文章的前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;
这与您的代码不同,它为每个article_from
最多返回5条记录,但它与您的初始描述一致。
在主查询中轻松地添加表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;
答案 1 :(得分:1)
带有join lateral
select o.id as from_id, p.article_to as to_id, a.title, a.journal_id, a.pub_date_p from articles o
join lateral (
select i.article_to from article_relationship i
where i.article_from = o.id
order by score desc
limit 5
) p on true
INNER JOIN articles a on a.id = p.article_to
where o.id IN (18329382, 61913904, 66538293, 66540477, 66496909)
order by o.id;