SELECT 个帖子及其评论

SELECT posts and their comments

我有三个 table:userspostscomments

如何 SELECT 前三个 post,每个都有评论数和前三个评论?

示例:SQL Fiddle

目标是打造一个像下面这样的table

预期输出:

-- 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 个 post 和 row_number 以仅包含每个 post 的前 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 post 和评论

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

编辑语法和列名:

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

了解预期输出背后的逻辑

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

  1. 获得前三个posts
  2. 获取他们的前三个评论
  3. 为列 comment_idbody
  4. 添加具有不同逻辑的 1 和 2 的结果

逻辑上的差异如下:

每行代表一个 post:

  • comment_id 中存储该 post
  • 的评论数
  • user_id 中存储写了 post
  • 的用户
  • body 中存储 post
  • 的正文
  • created_at 中存储创建 post 时的时间戳

虽然对于代表 comment 的每一行,逻辑是类比的(但对于评论,而不是 post),但 comment_id 列除外,其中您要存储评论 id.

查询及说明

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

首先,取前三个 post 并为它们建立行,计算每个评论的评论数。然后,将那些 posts 行与评论行合并,并使用 row_number() 函数将输出中的评论行限制为每个 post.

最多 3 个

0 指定为 post 的行号意味着它们满足 rn <= 3.

的条件

为了按照您的意愿对输出进行排序,以便对每个 post 他们的评论进行排序,我添加了一个 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;