老实说,我不知道如何为此提供更好的标题:(
基本上我有这3张表
Table "public.users"
Column | Type | Modifiers
--------+-----------------------+----------------------------------------------------
id | integer | not null default nextval('users_id_seq'::regclass)
name | character varying(40) |
Indexes:
"users_pkey" PRIMARY KEY, btree (id)
Referenced by:
TABLE "comments" CONSTRAINT "comments_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE
Table "public.comments"
Column | Type | Modifiers
---------+---------+-------------------------------------------------------
id | integer | not null default nextval('comments_id_seq'::regclass)
user_id | integer |
content | text |
Indexes:
"comments_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"comments_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE
Table "public.votes"
Column | Type | Modifiers
------------+---------+----------------------------------------------------
id | integer | not null default nextval('votes_id_seq'::regclass)
up | boolean | default false
comment_id | integer |
Indexes:
"votes_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"votes_comment_id_fkey" FOREIGN KEY (comment_id) REFERENCES comments(id) ON UPDATE CASCADE ON DELETE CASCADE
我想选择所有用户(包括那些没有评论的用户)并为每个用户添加3条评论,然后为每条评论选择2票(包括那些没有任何投票的评论)
到目前为止,我为每个用户选择3条评论的查询
SELECT users.id as userId, comments.id as commentId, users.name, comments.content, comments.rn
FROM users
LEFT JOIN (
SELECT *, row_number() OVER (PARTITION BY comments.user_id) as rn FROM comments
) as comments
ON users.id = comments.user_id
WHERE comments.rn <= 3 OR comments.rn IS NULL;
答案 0 :(得分:2)
因为对投票的评论和评论的用户都具有1对多的关系,所以两个联接都会为每个用户提供CxV(3x2 = 6)行。
由于评论的投票次数超过1次时评论会重复,因此请使用dense_rank()
代替row_number()
,以便“重复”评论具有相同的排名并包含在{{1}中}标准
rn < 4
答案 1 :(得分:2)
你有正确的想法。继续吧:
SELECT u.id as userId, c.id as commentId, u.name, c.content, c.rn
FROM users u LEFT JOIN
(SELECT c.*,
ROW_NUMBER() OVER (PARTITION BY c.user_id) as rn
FROM comments c
) c
ON u.id = c.user_id LEFT JOIN
(SELECT v.*,
ROW_NUMBER() OVER (PARTITION BY v.comment_id) as rn
FROM votes v
) v
ON c.id = v.comment_id
WHERE (c.rn <= 3 OR c.rn IS NULL) and
(v.rn <= 2 or v.rn IS NULL);
答案 2 :(得分:2)
可能它更适合索引:
select
*
from
users u
left join lateral (select * from comments c where u.id = c.user_id order by c.id limit 3) c on (u.id = c.user_id)
left join lateral (select * from votes v where c.id = v.comment_id order by v.id limit 2) v on (c.id = v.comment_id)