MySQL GROUP BY с тремя таблицами - PullRequest
2 голосов
/ 04 апреля 2010

У меня есть следующие таблицы:

posts (post_id, content, etc) 

comments (comment_id, post_id, content, etc)

posts_categories (post_category_id, post_id, category_id)

и этот запрос:

SELECT `p`.*
     , COUNT(comments.comment_id) AS cmts
     , posts_categories.*
     , comments.* 
  FROM `posts` AS `p` 
  LEFT JOIN `posts_categories` 
    ON `p`.post_id = `posts_categories`.post_id 
  LEFT JOIN `comments` 
    ON `p`.post_id = `comments`.post_id 
GROUP BY `p`.`post_id`

Есть три комментария к post_id = 1 и четыре всего. В posts_categories есть две строки, обе назначены post_id = 1. У меня есть четыре строки в сообщениях.

Но если я сделаю запрос выше, я получу результат 6 для COUNT(comments.comment_id) при post_id = 1 Как это возможно? Я предполагаю, что ошибка где-то в предложении GROUP BY, но я не могу понять, где.

Есть предложения?

Ответы [ 3 ]

1 голос
/ 04 апреля 2010

В первом приближении попробуйте

SELECT `p`.*
     , COUNT(DISTINCT comments.comment_id) AS cmts
     , posts_categories.*
     , comments.* 
  FROM `posts` AS `p` 
  LEFT JOIN `posts_categories` 
    ON `p`.post_id = `posts_categories`.post_id 
  LEFT JOIN `comments` 
    ON `p`.post_id = `comments`.post_id 
GROUP BY `p`.`post_id`

РЕДАКТИРОВАТЬ:

Однако COUNT (поле DISTINCT) дороже, чем COUNT (поле), и его следует избегать, если не нужно.Поскольку вы этого не ожидаете, я бы сказал, что в вашем случае это не нужно.

Ваша проблема возникает из-за того, что ваши объединения возвращают 3 (комментарии) x 2 (категории) = 6 строк.Я не знаю, для чего вы используете результаты, но, возможно, вам следует переосмыслить свой запрос.

0 голосов
/ 04 апреля 2010

Вы получите шесть (6) комментариев, потому что ваш набор результатов выглядит примерно так:
(обратите внимание на две группы по три строки в каждой; по одной для каждой категории сообщений - сокращенно pcat *)

post_id  cmts  post_cat  comments
1        6     pcat1     comment text...
1        6     pcat1     comment text...
1        6     pcat1     comment text...
1        6     pcat2     comment text...
1        6     pcat2     comment text...
1        6     pcat2     comment text...

Вместо этого вы можете сделать что-то вроде этого:

  SELECT `p`.post_id, 
         COUNT(comments.comment_id) AS cmts, 
         COUNT(posts_categories.) AS categories
    FROM `posts` AS `p` 
         LEFT JOIN `posts_categories` 
         ON `p`.post_id = `posts_categories`.post_id 
         LEFT JOIN `comments` 
         ON `p`.post_id = `comments`.post_id 
GROUP BY `p`.`post_id`
0 голосов
/ 04 апреля 2010

Полагаю, у вас более одной категории!

ли

SELECT P.post_id
     , PC.post_category_id
     , COUNT(C.comment_id) AS cmts
  FROM `posts` AS P 
  LEFT JOIN `posts_categories` as PC
    ON `p`.post_id = `posts_categories`.post_id 
  LEFT JOIN `comments` as C
    ON P.post_id = C.post_id 
GROUP BY P.post_id, PC.post_category_id

дать вам «понятный» результат?

Кстати В предложении GROUP BY должны быть все поля, которые не агрегированы ...

...