【问题标题】:LIMIT MySQL subquery using variable value before LEFT JOIN在 LEFT JOIN 之前使用变量值限制 MySQL 子查询
【发布时间】:2018-04-05 15:10:25
【问题描述】:

我有这个 MySQL 表 posts:

id | content       | parentid | userid
--------------------------------------
01 | Post test #1  | 0        | 1
02 | Post test #2  | 0        | 1
03 | Comment #1    | 1        | 2
04 | Comment #2    | 1        | 1
05 | Post test #3  | 0        | 3
06 | Comment #3    | 1        | 2
07 | Comment #4    | 2        | 5
08 | Comment #5    | 5        | 6
09 | Comment #6    | 1        | 4
10 | Post test #4  | 0        | 4

这只是stackoverflow的一个例子

现在我需要为每个帖子限制 cmets,到目前为止我已经使用了这个查询:

SELECT
    `posts`.`id` AS `post_id`,
    `posts`.`content` AS `post_content`,
    `posts`.`parentid` AS `post_parentid`,
    `posts`.`userid` AS `post_userid,

    `comments`.`id`, 0 AS `comment_id`,
    `comments`.`content` AS `comment_content`,
    `comments`.`parentid` AS `comment_parentid`,
    `comments`.`userid` AS `comment_userid,
    IF( IFNULL( `comments`.`id`, 0 ) > 0, "comment", "post" ) AS `contenttype`

FROM `posts` AS `posts`
LEFT JOIN ( SELECT "" AS `hello` ) AS `useless` ON @pid := `posts`.`id`
LEFT JOIN ( SELECT
        `posts`.`id` AS `id`,
        `posts`.`id` AS `id`,
        `posts`.`id` AS `id`,
        `posts`.`id` AS `id`
    FROM `posts`
    WHERE `posts`.`parentid` = @pid
    LIMIT 10
    ) AS `comments`ON `comments`.`parentid` = `posts`.`id`
WHERE
    `posts`.`userid` = {USERID}

为了存档这个,我加入了一个useless“表”,只是为了更新@pid(parentid)变量。

这是限制子查询结果的唯一方法吗?我不喜欢 useless JOIN 的想法。

如果我必须在上面的示例中限制posts 而不会影响 cmets LIMIT。可以给我一个更好的查询吗?

【问题讨论】:

  • 无论如何,即使是这个查询也没有像预期的那样工作。

标签: mysql subquery limit


【解决方案1】:

发布此问题的真正原因是为每个评论加载 10 个 cmets 和 10 个子 cmets。关于我要求加载帖子和 cmets 的问题,所以想法是一样的。

我的问题中发布的示例不起作用,因为子查询将在变量 @pid 更新之前执行。

因为我使用的是 PHP,所以我在这里发布了针对这种情况的 MySQL 和 PHP 解决方案。

1 - 首先让我们用这个 SQL 查询加载帖子

SELECT
    `posts`.`id` AS `id`,
    `posts`.`content` AS `content`,
    `posts`.`parentid` AS `parentid`,
    `posts`.`userid` AS `userid

 FROM `posts` AS `posts`
 WHERE
    `posts`.`userid` = {USERID}
    AND
    `posts`.`parentid` = '0'
 ORDER BY `posts`.`id` DESC
 LIMIT 10

2 - 将帖子信息存储在 $posts 数组中:

$posts   = [];
while   ( $row = $result->fetch_object() )
        {
        $posts[] = (object) [ "id"       => $row->id,
                              "content"  => $row->content,
                              "userid"   => $row->userid,
                              "comments" => []
                              ];
        }

3 - 准备 SQL 以加载 cmets:

$size    = count( $posts );
$sql     = "";
for     ( $i = 0; $i < $size; $i ++ )
        {
        $sql     .= ( $sql != "" ? "UNION ALL " : "" )
                 . "( "
                 . "SELECT "
                 . "`comments`.`id` AS `id`, "
                 . "`comments`.`content` AS `content`, "
                 . "`comments`.`parentid` AS `parentid`, "
                 . "`comments`.`userid` AS `userid "
                 . "FROM `posts` AS `comments` "
                 . "WHERE "
                 . "`comments`.`parentid` = '" . $post[ $i ]->id . "' "
                 . "ORDER BY `comments`.`id` ASC "
                 . "LIMIT 10 "
                 . ") ";
        }

4 - 执行 $sql 代码后,让我们为每个帖子存储 cmets:

while ( $row = $result->fetch_object() )
      {
      $posts[ $row->parentid ]->comments[] = (object)[
                               "id"       => $row->id,
                               "content"  => $row->content,
                               "userid"   => $row->userid,
                               ];
      }

如您所见,这也可用于 cmets(而不是 posts)和子 cmets(而不是 cmets)。这次 MySQL 变量没有帮助。当然,要创建分页,您必须在表格中添加额外的字段 (replies) 并在创建评论时更新。

如果有人有更好的解决方案欢迎。

【讨论】:

    猜你喜欢
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    • 2015-03-16
    • 1970-01-01
    • 2015-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多