SQL - 根据来自多个 table 的信息对 table 进行排序
SQL - ordering table by information from multiple tables
问题的标题可能不是很清楚 - 我不太确定如何命名这个问题,但我希望我的解释能让我的问题更清楚。
我有 3 个 table:
[1] 得分
id
rating_type
1
UPVOTE
2
UPVOTE
3
DOWNVOTE
4
UPVOTE
5
DOWNVOTE
6
DOWNVOTE
[2] post_score
post_id
score_id
1
1
1
2
1
3
2
4
2
5
2
6
和[3]post
id
title
1
title1
2
title2
我的目标是按分数订购[3]posttable
假设UPVOTE代表值为1,DOWNVOTE代表值为-1;在这个例子中,post where id = 1 有3个分数与之相关,它们的值为UPVOTE,UPVOTE,DOWNVOTE,使得这个post的“数字分数”:2;
同样,post 其中 id = 2,也有 3 个分数,这些值是:UPVOTE、DOWNVOTE、DOWNVOTE,使得“数字分数”:-1;
我如何按这个分数订购 post table?在此示例中,如果我按分数升序排序,我会期望得到以下结果:
id
title
2
title2
1
title1
我的尝试没有成功,目前我被困在这个查询中,还没有真正做任何有用的事情:
WITH fullScoreInformation AS (
SELECT * FROM score s
JOIN post_score ps ON s.id = ps.score_id),
upvotes AS (SELECT * FROM fullScoreInformation WHERE rating_type = 'UPVOTE'),
downvotes AS (SELECT * FROM fullScoreInformation WHERE rating_type = 'DOWNVOTE')
SELECT p.id, rating_type, title FROM post p JOIN fullScoreInformation fsi on p.id = fsi.post_id
我正在使用 PostgreSQL。查询将在我的 Spring 引导应用程序中使用(我通常使用本机查询)。
也许这个数据结构不好,我应该以不同的方式构造我的实体?
My goal is to order post table by score. Assume UPVOTE represents value of 1 and DOWNVOTE value of -1
一个选项使用子查询来计算每个 post:
的赞成票和反对票
select p.*, s.*
from post p
cross join lateral (
select
count(*) filter(where s.rating_type = 'UPVOTE' ) as cnt_up,
count(*) filter(where s.rating_type = 'DOWNVOTE') as cnt_down
from post_score ps
inner join score s on s.id = ps.score_id
where ps.post_id = p.id
) s
order by s.cnt_up - s.cnt_down desc
Perhaps this data structure is bad and I should have constructed my entities differently ?
就目前而言,我认为不需要两个不同的 tables post_score
和 score
。对于您显示的数据,这是 1-1 关系,因此只需一个 table 就足够了,存储 post id 和评级类型。
你最好使用 LEFT
加入,否则你不会得到没有投票的帖子。然后聚合以获得分数的过滤总和。然后将这些总和相加,应用 coalesce()
得到 0
没有投票的帖子并按结果排序。
SELECT p.id,
p.title
FROM post p
LEFT JOIN post_score ps
ON ps.post_id = p.id
LEFT JOIN score s
ON s.id = ps.score_id
GROUP BY p.id,
p.title
ORDER BY coalesce(sum(1) FILTER (WHERE rating_type = 'UPVOTE')
+
sum(-1) FILTER (WHERE rating_type = 'DOWNVOTE'),
0);
我同意 GMB 关于多余的评论 table。
问题的标题可能不是很清楚 - 我不太确定如何命名这个问题,但我希望我的解释能让我的问题更清楚。
我有 3 个 table:
[1] 得分
id | rating_type |
---|---|
1 | UPVOTE |
2 | UPVOTE |
3 | DOWNVOTE |
4 | UPVOTE |
5 | DOWNVOTE |
6 | DOWNVOTE |
[2] post_score
post_id | score_id |
---|---|
1 | 1 |
1 | 2 |
1 | 3 |
2 | 4 |
2 | 5 |
2 | 6 |
和[3]post
id | title |
---|---|
1 | title1 |
2 | title2 |
我的目标是按分数订购[3]posttable
假设UPVOTE代表值为1,DOWNVOTE代表值为-1;在这个例子中,post where id = 1 有3个分数与之相关,它们的值为UPVOTE,UPVOTE,DOWNVOTE,使得这个post的“数字分数”:2;
同样,post 其中 id = 2,也有 3 个分数,这些值是:UPVOTE、DOWNVOTE、DOWNVOTE,使得“数字分数”:-1;
我如何按这个分数订购 post table?在此示例中,如果我按分数升序排序,我会期望得到以下结果:
id | title |
---|---|
2 | title2 |
1 | title1 |
我的尝试没有成功,目前我被困在这个查询中,还没有真正做任何有用的事情:
WITH fullScoreInformation AS (
SELECT * FROM score s
JOIN post_score ps ON s.id = ps.score_id),
upvotes AS (SELECT * FROM fullScoreInformation WHERE rating_type = 'UPVOTE'),
downvotes AS (SELECT * FROM fullScoreInformation WHERE rating_type = 'DOWNVOTE')
SELECT p.id, rating_type, title FROM post p JOIN fullScoreInformation fsi on p.id = fsi.post_id
我正在使用 PostgreSQL。查询将在我的 Spring 引导应用程序中使用(我通常使用本机查询)。
也许这个数据结构不好,我应该以不同的方式构造我的实体?
My goal is to order post table by score. Assume UPVOTE represents value of 1 and DOWNVOTE value of -1
一个选项使用子查询来计算每个 post:
的赞成票和反对票select p.*, s.*
from post p
cross join lateral (
select
count(*) filter(where s.rating_type = 'UPVOTE' ) as cnt_up,
count(*) filter(where s.rating_type = 'DOWNVOTE') as cnt_down
from post_score ps
inner join score s on s.id = ps.score_id
where ps.post_id = p.id
) s
order by s.cnt_up - s.cnt_down desc
Perhaps this data structure is bad and I should have constructed my entities differently ?
就目前而言,我认为不需要两个不同的 tables post_score
和 score
。对于您显示的数据,这是 1-1 关系,因此只需一个 table 就足够了,存储 post id 和评级类型。
你最好使用 LEFT
加入,否则你不会得到没有投票的帖子。然后聚合以获得分数的过滤总和。然后将这些总和相加,应用 coalesce()
得到 0
没有投票的帖子并按结果排序。
SELECT p.id,
p.title
FROM post p
LEFT JOIN post_score ps
ON ps.post_id = p.id
LEFT JOIN score s
ON s.id = ps.score_id
GROUP BY p.id,
p.title
ORDER BY coalesce(sum(1) FILTER (WHERE rating_type = 'UPVOTE')
+
sum(-1) FILTER (WHERE rating_type = 'DOWNVOTE'),
0);
我同意 GMB 关于多余的评论 table。