选择帖子及其评论

问题描述 投票:0回答:3

我有三张桌子:

users
posts
comments

我如何

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
sql postgresql join greatest-n-per-group
3个回答
1
投票

理解预期输出背后的逻辑

您对预期输出有相当复杂的需求。根据我从您的 sql fiddle 中了解到的预期结果,您想要:

  1. 获得前三篇文章
  2. 获取他们的前三条评论
  3. 将 1 和 2 的结果附加到列
    comment_id
    body
  4. 的不同逻辑

逻辑上的差异似乎如下:

对于代表一个post的每一行:

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

虽然对于代表 comment 的每一行,逻辑是类似的(但对于评论,而不是帖子),但您要存储评论

comment_id
id
列除外。

查询及解释

有关实例,请参阅 SQL fiddle

首先,获取前三个帖子并为它们建立行,计算每个帖子的评论数。然后,将这些帖子行与评论行合并,并使用

row_number()
函数将输出中的评论行限制为每个帖子最多 3 行。

0
指定为帖子的行号意味着它们满足
rn <= 3
的条件。

为了按照您的意愿对输出进行排序,以便每个帖子的评论都紧随其后排序,我添加了一个

order_column
以便能够将其包含在
ORDER BY
中。

WITH first_posts AS (
    SELECT p.id AS post_id, COUNT(c.id) AS comment_id, p.user_id, p.body, p.created_at
    FROM (SELECT * FROM posts ORDER BY id LIMIT 3) AS p
    LEFT JOIN comments AS c
    ON p.id = c.post_id
    GROUP BY 1, 3, 4, 5
)
SELECT post_id, comment_id, user_id, body, created_at
FROM (
    SELECT 1 AS type, post_id, comment_id, user_id, body, created_at, 0 AS r
    FROM first_posts
    UNION ALL
    SELECT 2 AS type, p.post_id, c.id, c.user_id, c.body, c.created_at, 
        ROW_NUMBER() OVER (PARTITION BY p.post_id ORDER BY c.id) AS r
    FROM first_posts AS p
    INNER JOIN comments AS c
    ON p.post_id = c.post_id
    ORDER BY post_id, type, comment_id
) AS f
WHERE r <= 3;

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 个帖子和评论

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
投票

编辑语法和列名称:

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
© www.soinside.com 2019 - 2024. All rights reserved.