选择帖子及其评论

时间:2016-08-28 14:52:28

标签: sql postgresql join greatest-n-per-group

我有三个表:userspostscomments

我如何SELECT前三个帖子,每个帖子都有评论数和前三条评论?

示例:SQL Fiddle

目标是构建一个类似下面的表

  • 每个post_id分组的第一行是帖子
  • comment_id是帖子的评论数
  • 下一行是该帖子的前三个评论

预期输出:

-- post_id   comment_id   user_id   body               created_at
-- 1         4            1         Hello. I'm Jane.   August, 28 2016 14:12:01
-- 1         1            2         Nice post, Jane.   August, 28 2016 14:12:01
-- 1         2            1         Thank you, John.   August, 28 2016 14:12:01
-- 1         3            2         You're welcome.    August, 28 2016 14:12:01
-- 2         2            1         This is post 2.    August, 28 2016 14:12:01
-- 2         5            2         I like this.       August, 28 2016 14:12:01
-- 2         6            1         Why, thank you.    August, 28 2016 14:12:01
-- 3         0            1         This is post 3.    August, 28 2016 14:12:01

3 个答案:

答案 0 :(得分:1)

您可以使用子查询将您的选择限制为前3个帖子,row_number只包含每个帖子的前3个评论:

SELECT * FROM (
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY c.post_id ORDER BY c.id) rn
    FROM posts p
    JOIN comments c ON c.post_id = p.id
    WHERE p.id IN (SELECT id FROM posts ORDER BY id LIMIT 3)
) t WHERE rn <= 3

或者如果你想要前3个帖子&amp;每个用户的评论

SELECT * FROM (
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY c.post_id ORDER BY c.id) comments_rn,
        ROW_NUMBER() OVER (PARTITION BY p.user_id ORDER BY p.id) post_rn        
    FROM posts p
    JOIN comments c ON c.post_id = p.id
    JOIN users u ON u.id = p.user_id
) t WHERE comments_rn <= 3 and post_rn <= 3

答案 1 :(得分:1)

了解预期输出背后的逻辑

您对预期输出的需求非常复杂。根据我对 sql fiddle 的理解,查看预期结果,您希望:

  1. 获得前三个帖子
  2. 获得前三条评论
  3. 将结果从1和2附加到列comment_idbody的不同逻辑
  4. 逻辑上的差异似乎如下:

    代表帖子的每一行

    • comment_id商店中对该帖子的评论数量
    • user_id中存储撰写帖子的用户
    • body存储帖子正文
    • created_at中存储帖子创建时的时间戳

    对于代表评论的每一行,逻辑是类比的(但对于评论,而不是帖子),comment_id列除外,您要存储评论{{1 }}

    查询和解释

    有关实时示例,请查看 SQL fiddle

    首先,前三个帖子并为他们构建行,计算每个帖子的评论。然后,将这些帖子行与注释行结合起来,并使用id函数将输出中的注释行限制为每个帖子最多3个。

    row_number()指定为帖子的行号意味着它们符合0的条件。

    要按照您的意愿对输出进行排序,以便每个帖子的评论都在其后排序,我已添加了rn <= 3,以便能够将其添加到order_column

    ORDER BY

答案 2 :(得分:0)

编辑的语法和列名:

Select id, name, p.*, c.* 
from users u
    join posts p on p.User_Id = u.Id
       and (Select count(*) From posts 
            where user_Id = u.Id
               and created_at <= p.created_at) <= 3
    join comments c on c.post_Id = p.Id
       and (Select count(*) From comments 
            where post_Id = p.Id 
               and created_at <= c.created_at) <= 3