使用MySQL查询每个组的top N


Query for top N per group with pagination using MySQL

我在SO上搜索了一些答案,但没有一个能达到我想要的效果,所以这里有另一个关于每组前N的问题。

<<p> DB结构/strong>

目前我有一个Post表如下:

post_id | post_title | post_text

和注释表如下:

comment_id | post_id | comment_text | comment_date | ...

  • 我想获得comment_date desc订购的每篇文章的前n条评论,并支持分页。如果可能的话,每个帖子必须返回n条评论,例如,如果一个帖子有10条评论,应该返回3条,如果一个帖子有2条评论,只能返回2条。
  • 应该返回所有的注释字段。
  • 只有post_id, post_title, post_text需要返回,但如果我们可以返回所有字段,那将是伟大的。
  • 如果可能的话,一个帖子应该只出现一次,即如果它在第1页,那么在第2页就不会被考虑在内(请参见下面的例子)。我认为这比允许一个帖子出现几次更容易实现。

我有以下帖子:

post_id | post_title | post_text
++++++++++++++++++++++++++++++++
      1 | ...         | ...
      2 | ...         | ...
      3 | ...         | ...
      4 | ...         | ...

和以下注释(由comment_date desc排序,date 12date 11更新):

comment_id | post_id | comment_date | ...
+++++++++++++++++++++++++++++++++++++++++
        12 |       1 | date 12      | ...
        11 |       2 | date 11      | ...
        10 |       2 | date 10      | ...
         9 |       2 | date 9       | ...
         8 |       3 | date 8       | ...
         7 |       1 | date 7       | ...
         6 |       4 | date 6       | ...
         5 |       2 | date 5       | ...
         4 |       2 | date 4       | ...
         3 |       1 | date 3       | ...
         2 |       1 | date 2       | ...
         1 |       1 | date 1       | ...

假设我每页限制6个评论,n是3个。预期结果为:

Page 1:
comment_id | post_id | comment_date | ...
+++++++++++++++++++++++++++++++++++++++++
        12 |       1 | date 12      | ...
        11 |       2 | date 11      | ...
        10 |       2 | date 10      | ...
         9 |       2 | date 9       | ...
         7 |       1 | date 7       | ...
         3 |       1 | date 3       | ...
Page 2
comment_id | post_id | comment_date | ...
+++++++++++++++++++++++++++++++++++++++++
         8 |       3 | date 8       | ...
         6 |       4 | date 6       | ...

我尝试过类似这样的事情:Top N每组与多个表连接,但如果我们按comment_date desc排序,没有保证有确切的N个结果返回。

您正在请求的代码,也填写我注释的TODO。

<?php
$start = isset($_GET['start']) ? $_GET['start'] : 0;
$max_record = 3;
$sql = "
  SELECT * FROM 
  post p INNER JOIN comment c
  ON p.post_id = c.post_id
  ORDER BY c.comment_date DESC LIMIT $start, $max_record
";
// TODO: create sql query.
$next = $start + $max_record;
?>
<p>SQL Start: <?php echo $start ?></p>
<p>SQL Max Record: <?php echo $max_record ?></p>
<a href="index.php?start=<?php echo $next ?>">Next</a>

我不需要解释所有的事情,甚至是我提供的不安全脚本,但逻辑是存在的。