帖子的SQL分页和每篇帖子的3条最新评论

时间:2015-03-27 14:30:19

标签: mysql

我有一个MySQL查询,每个帖子最多可以选择3条评论(如果有的话):

SELECT p.*, c.* 
FROM posts p 
LEFT JOIN comments c ON (p.post_id=c.post_id) 
AND c.comment_id > 
   (SELECT comment_id FROM comments 
    WHERE post_id=p.post_id ORDER BY comment_id DESC LIMIT 3
   )

我还想对这些帖子进行分页。例如,我想限制每页只有10个帖子。

仅供澄清 - 我的意思是10个DISTINCT帖子用于分页,而不是3个帖子在结果查询中,3个评论用于每个帖子。我的意思是这些帖子有10个不同的帖子*评论(每个帖子最多3个)。

如何在此查询中的帖子中引入分页?

另一个解决方案:

此外,我还为此任务找到了另一个解决方案:

SELECT *
FROM
(
    SELECT *
    FROM posts
    LIMIT 0, 10
) p
LEFT JOIN
(
    SELECT c.*, 
        @rownumber := CASE WHEN @post_id = post_id THEN @rownumber + 1 ELSE 1 END AS n,
        @post_id := post_id
    FROM comments c,
    (SELECT @rownumber := 0, @post_id := 0) r    
    ORDER BY post_id DESC
) c ON p.post_id = c.post_id
WHERE c.post_id IS NULL OR n BETWEEN 1 and 3

1 个答案:

答案 0 :(得分:3)

基本答案

您在 SELECT 中使用的语法与您的评论相同:

LIMIT 0, 10

但是,您的查询有使用LIMIT 3, 1(仅返回第四行)而不是LIMIT 0, 3LIMIT 3的错误。

扩展答案

这不是一个容易编写的查询,因为它非常复杂,但我在下面编写了一个更简单的版本,可以满足您的需求。如果您想要选择30条评论,每篇文章最多3条评论,这会更容易,但这显然不是您想要做的。

基本上,查询会返回前10个posts,每个评论都有2个字段(comments.idcomments.comment),这使得这三个评论共有6个字段。

如何通过使用带有评论表的三个LEFT JOIN来实现这一点,每个评论表与之前的id具有不同的LEFT JOIN。这会为每个帖子创建最多三行,因此我们使用GROUP BY p.id将它们全部合并为一行 该查询还使用ORDER BY p.id ASC,因为使用LIMIT而不使用ORDER BY是不可预测的(数据库引擎在大多数情况下会在内部对结果应用ORDER BY子句。)

  

注意:如果INDEX上有comments.post_id,则此查询速度非常快。

MySQL查询

SELECT p.*,
       c1.id AS comment1_id, c1.comment AS comment1,
       c2.id AS comment2_id, c2.comment AS comment2,
       c3.id AS comment3_id, c3.comment AS comment3

FROM posts AS p

LEFT JOIN comments AS c1 ON c1.post_id = p.id
LEFT JOIN comments AS c2 ON c2.post_id = p.id AND c2.id <> c1.id
LEFT JOIN comments AS c3 ON c3.post_id = p.id AND c3.id <> c1.id AND c3.id <> c2.id

GROUP BY p.id
ORDER BY p.id ASC
LIMIT 0, 10;

结果

| id |       post | comment1_id |  comment1 | comment2_id |  comment2 | comment3_id |  comment3 |
|----|------------|-------------|-----------|-------------|-----------|-------------|-----------|
|  1 |  Post 1... |           1 | Comment 1 |           2 | Comment 2 |      (null) |    (null) |
|  2 |  Post 2... |           3 | Comment 3 |           8 | Comment 8 |           9 | Comment 9 |
|  3 |  Post 3... |      (null) |    (null) |      (null) |    (null) |      (null) |    (null) |
|  4 |  Post 4... |           4 | Comment 4 |           5 | Comment 5 |           7 | Comment 7 |
|  5 |  Post 5... |      (null) |    (null) |      (null) |    (null) |      (null) |    (null) |
|  6 |  Post 6... |      (null) |    (null) |      (null) |    (null) |      (null) |    (null) |
|  7 |  Post 7... |      (null) |    (null) |      (null) |    (null) |      (null) |    (null) |
|  8 |  Post 8... |      (null) |    (null) |      (null) |    (null) |      (null) |    (null) |
|  9 |  Post 9... |      (null) |    (null) |      (null) |    (null) |      (null) |    (null) |
| 10 | Post 10... |           6 | Comment 6 |      (null) |    (null) |      (null) |    (null) |
  

有关在线示例,请参阅http://sqlfiddle.com/#!9/182db/4

通过检查null的字段,您可以检查该帖子是否有评论,以及发布的评论数量。

  

注意:您应该坚持使用大写作为SQL关键字,因为这是行业最佳惯例。