我怎样才能 select 每个主题的最高 post 并在给定此模式设计的情况下将它们关联起来?
How can I select the highest post per topic and associate them given this schema design?
我正在为一个网站开发一个小型论坛组件,我正在创建一个页面,我想在其中显示每个主题及其评分最高的答案。表格如下所示:
POST USER TOPIC
id id id
date name title
text bio date
views
likes
topic_id
author_id
我的查询是这样的:
select
u.id, u.name, u.bio,
p.id, p.date, p.text, p.views, p.likes,
t.id, t.title, t.date
from
( select p.id, max(p.likes) as likes, p.topic_id
from post as p group by p.topic_id ) as q
inner join post as p on q.id = p.id
inner join topic as t on t.id = q.topic_id
inner join user as u on u.id = p.author_id
order by date desc;
我运行遇到的问题之一是"q"。 Postgresql 不会让我 运行 "q" 查询,因为它希望 "p.id" 在 "group by" 子句或聚合函数中。我尝试使用 "distinct on (p.id)" 但我收到相同的错误消息:p.id must appear in the GROUP BY clause or be used in an aggregate function.
没有 p.id 属性,我无法将它有意义地 link 到其他表;还有其他方法可以实现吗?
;WITH cte AS (
SELECT
u.id AS UserId
,u.name
,u.bio
,p.id AS PostId
,p.[date] AS PostDate
,p.text
,p.views
,p.Likes
,t.id AS TopidId
,t.title
,t.[date] AS TopicDate
,p.Likes
,ROW_NUMBER() OVER (PARTITION BY t.id ORDER BY p.Likes DESC, p.[date] DESC) AS RowNum
,DENSE_RANK() OVER (PARTITION BY t.id ORDER BY p.Likes DESC) AS RankNum
FROM
topic t
INNER JOIN post p
ON t.id = p.topic_id
INNER JOIN [user] u
ON p.author_id = u.id
)
SELECT *
FROM
cte
WHERE
RowNum = 1
;
如果您想查看最喜欢的人的关系,请将 RowNum
切换到 RankNum
这是一个常见的需求:分组时,显示每个组的 first/last a
按其他一些标准 b
排名。我没有它的名字,但是 this seems to be the canonical question. You can see there are a lot of choices! My favorite solution is probably a lateral join:
SELECT u.id, u.name, u.bio,
p.id, p.date, p.text, p.views, p.likes,
t.id, t.title, t.date
FROM topic t
LEFT OUTER JOIN LATERAL (
SELECT *
FROM post
WHERE post.topic_id = t.id
ORDER BY post.likes DESC
LIMIT 1
) p
ON true
LEFT OUTER JOIN "user" u
ON p.author_id = u.id
;
SELECT
u.id AS uid, u.name, u.bio
, p.id AS pid, p."date" AS pdate, p.text, p.views, p.likes
, t.id AS tid, t.title, t."date" AS tdate
FROM post p
JOIN topic t ON t.id = p.topic_id
JOIN user u ON u.id = p.author_id
WHERE NOT EXISTS ( SELECT *
FROM post nx
WHERE nx.topic_id = p.topic_id
AND nx.likes > p.likes)
ORDER BY p."date" DESC
;
我正在为一个网站开发一个小型论坛组件,我正在创建一个页面,我想在其中显示每个主题及其评分最高的答案。表格如下所示:
POST USER TOPIC
id id id
date name title
text bio date
views
likes
topic_id
author_id
我的查询是这样的:
select
u.id, u.name, u.bio,
p.id, p.date, p.text, p.views, p.likes,
t.id, t.title, t.date
from
( select p.id, max(p.likes) as likes, p.topic_id
from post as p group by p.topic_id ) as q
inner join post as p on q.id = p.id
inner join topic as t on t.id = q.topic_id
inner join user as u on u.id = p.author_id
order by date desc;
我运行遇到的问题之一是"q"。 Postgresql 不会让我 运行 "q" 查询,因为它希望 "p.id" 在 "group by" 子句或聚合函数中。我尝试使用 "distinct on (p.id)" 但我收到相同的错误消息:p.id must appear in the GROUP BY clause or be used in an aggregate function.
没有 p.id 属性,我无法将它有意义地 link 到其他表;还有其他方法可以实现吗?
;WITH cte AS (
SELECT
u.id AS UserId
,u.name
,u.bio
,p.id AS PostId
,p.[date] AS PostDate
,p.text
,p.views
,p.Likes
,t.id AS TopidId
,t.title
,t.[date] AS TopicDate
,p.Likes
,ROW_NUMBER() OVER (PARTITION BY t.id ORDER BY p.Likes DESC, p.[date] DESC) AS RowNum
,DENSE_RANK() OVER (PARTITION BY t.id ORDER BY p.Likes DESC) AS RankNum
FROM
topic t
INNER JOIN post p
ON t.id = p.topic_id
INNER JOIN [user] u
ON p.author_id = u.id
)
SELECT *
FROM
cte
WHERE
RowNum = 1
;
如果您想查看最喜欢的人的关系,请将 RowNum
切换到 RankNum
这是一个常见的需求:分组时,显示每个组的 first/last a
按其他一些标准 b
排名。我没有它的名字,但是 this seems to be the canonical question. You can see there are a lot of choices! My favorite solution is probably a lateral join:
SELECT u.id, u.name, u.bio,
p.id, p.date, p.text, p.views, p.likes,
t.id, t.title, t.date
FROM topic t
LEFT OUTER JOIN LATERAL (
SELECT *
FROM post
WHERE post.topic_id = t.id
ORDER BY post.likes DESC
LIMIT 1
) p
ON true
LEFT OUTER JOIN "user" u
ON p.author_id = u.id
;
SELECT
u.id AS uid, u.name, u.bio
, p.id AS pid, p."date" AS pdate, p.text, p.views, p.likes
, t.id AS tid, t.title, t."date" AS tdate
FROM post p
JOIN topic t ON t.id = p.topic_id
JOIN user u ON u.id = p.author_id
WHERE NOT EXISTS ( SELECT *
FROM post nx
WHERE nx.topic_id = p.topic_id
AND nx.likes > p.likes)
ORDER BY p."date" DESC
;