1

这是我的查询

$getPosts = mysql_query ('SELECT `posts`.*, COUNT(`comments`.`comment_id`) 
                          FROM `posts` 
                          LEFT JOIN `comments` 
                          ON (`posts`.`post_id` = `comments`.`post_id`) 
                          ORDER BY `posts`.`post_id` DESC')
            or die(mysql_error());

然后循环遍历它...

while ($post = mysql_fetch_row($getPosts))
{
    echo $post[1] . ' ' . $post[4] . ' comments'; // example
}

一切正常,但仅适用于第一行。

现在,post_id 1 有 2 条评论。post_id 2 在数据库中没有评论。

我认为这是 JOIN 的工作原理,但我不明白。我认为 LEFT JOIN 只匹配左边的内容(所以 post_id),但我尝试了 INNER JOIN、OUTER JOIN 等。但它不起作用

4

1 回答 1

3

您的COUNT()聚合必须与GROUP BY子句一起使用。没有它,MySQL 将返回结果,但它们不会是您期望的结果,因为它会不确定地返回一个相关行。

SELECT
  `posts`.*, 
  `c`.`num_comments`
FROM
  `posts` 
  /* join against a subquery which retrieves the number of comments per post_id */
  LEFT JOIN (
    SELECT `post_id`, COUNT(*) AS `num_comments` 
    FROM `comments`
    GROUP BY `post_id` 
  ) AS c ON (`posts`.`post_id` = `c`.`post_id`) 
ORDER BY
  `posts`.`post_id` DESC

MySQL 可能会允许您在不使用子查询的情况下简化此操作,因为它不需要posts列出 from 中的每一列GROUP BY,但不建议这样做,因为它不适用于任何地方。

/* MySQL only, not recommended */
SELECT
  posts.*,
  COUNT(comments.comment_id) AS num_comments
FROM 
  posts
  LEFT JOIN comments ON posts.post_id = comments.post_id
GROUP BY posts.post_id

否则,您将需要列出 中posts的每一列,GROUP BY因为它们都是SELECT. posts这将起作用,因为联接只涉及与的一对多关系comments

当您在 PHP 中获取此行时,请使用 alias num_comments。建议使用mysql_fetch_assoc(), 并通过名称而不是数字键来访问列。

while ($post = mysql_fetch_assoc($getPosts))
{
    echo $post['post_id'] . ' ' . $post['num_comments'] . ' comments';
}

从长远来看,如上面评论中所述,考虑切换到更新的 API,例如 MySQLi 或 PDO,因为该mysql_*()扩展在下一个主要 PHP 版本中面临弃用。

于 2013-03-10T02:22:57.183 回答