Справка по SQL: агрегат COUNT, список записей и количество комментариев

0

Итак, что я намеревался сделать, это получить список записей/сообщений с их информацией о категории и пользователе, а также каждый из опубликованных комментариев. (записи, категории, пользователи и комментарии являются отдельными таблицами)

Этот запрос ниже извлекает записи в порядке, но, похоже, пропускает эти записи без комментариев. Насколько я вижу, JOINs хороши (LEFT JOIN в таблице комментариев), и запрос правильный. Что я пропустил?

SELECT entries.entry_id, entries.title, entries.content,
entries.preview_image, entries.preview_thumbnail, entries.slug,
entries.view_count, entries.posted_on, entry_categories.title AS category_title,
entry_categories.slug AS category_slug, entry_categories.parent AS category_parent,
entry_categories.can_comment AS can_comment, entry_categories.can_rate AS can_rate,
users.user_id, users.group_id, users.username, users.first_name, users.last_name,
users.avatar_small, users.avatar_big, users.score AS user_score, 
COUNT(entry_comments.comment_id) AS comment_count

FROM (entries)
JOIN entry_categories ON entries.category = entry_categories.category_id
JOIN users ON entries.user_id = users.user_id
LEFT JOIN entry_comments ON entries.entry_id = entry_comments.entry_id

WHERE `entries`.`publish` = 'Y'
AND `entry_comments`.`publish` = 'Y'
AND `entry_comments`.`deleted_at` IS NULL
AND `category` = 5

GROUP BY entries.entry_id, entries.title, entries.content,
entries.preview_image, entries.preview_thumbnail, entries.slug,
entries.view_count, entries.posted_on, category_title, category_slug,
category_parent, can_comment, can_rate, users.user_id, users.group_id,
users.username, users.first_name, users.last_name, users.avatar_big,
users.avatar_small, user_score

ORDER BY posted_on desc

edit: Я использую MySQL 5.0

Теги:

3 ответа

1
Лучший ответ

Ну, вы делаете левое соединение на entry_comments, с условиями:

`entry_comments`.`publish` = 'Y'
`entry_comments`.`deleted_at` IS NULL

Для записей без комментариев эти условия являются ложными. Думаю, это должно решить проблему:

WHERE `entries`.`publish` = 'Y'
AND (
        (`entry_comments`.`publish` = 'Y'
        AND `entry_comments`.`deleted_at` IS NULL)
    OR
        `entry_comments`.`id` IS NULL
    )
AND `category` = 5

В условии OR я помещаю entry_comments. id, считая, что это первичный ключ таблицы entry_comments, поэтому вы должны заменить его на реальный первичный ключ entry_comments.

  • 0
    классно! Одна проблема, однако, теперь кажется, что пропускаются записи с комментариями, имеющими ненулевое значение в deleted_at . Есть идеи ?
  • 0
    Ну, у вас есть условие «И entry_comments . deleted_at IS НЕДЕЙСТВИТЕЛЬНО», поэтому просто удалите его, если вы хотите, чтобы комментарии, не имеющие нулевого значения, в удаленном_катале.
Показать ещё 3 комментария
1

Это потому, что вы устанавливаете фильтр по столбцам в таблице entry_comments. Замените первый на:

AND IFNULL(`entry_comments`.`publish`, 'Y') = 'Y'

Поскольку ваш другой фильтр в этой таблице является IS NULL, это все, что вам нужно сделать, чтобы разрешить непревзойденные строки из LEFT JOIN.

  • 0
    замена: "AND entry_comments . publish = 'Y'" на "AND ISNULL ( entry_comments . publish , 'Y') = 'Y" "приводит к синтаксической ошибке. Или я ошибся?
  • 0
    Извините, в MySQL это IFNULL, а не ISNULL - отредактировал ответ.
Показать ещё 1 комментарий
0

Попробуйте изменить LEFT JOIN на LEFT OUTER JOIN

ИЛИ

Я не являюсь экспертом в этом стиле соединений SQL (больше у Oracle сам), но формулировка левого соединения побуждает меня полагать, что он присоединяется к entry_comments для записей с entry_comments слева, вы действительно хочу, чтобы это было наоборот (я думаю).

Итак, попробуйте что-то вроде:

ВНЕШНИЕ ВХОДНЫЕ ВХОДНЫЕ ЗАПИСИ НА ВХОДЕ. entry_id = entry_comments.entry_id

  • 1
    Нет, iirc LEFT OUTER JOIN является синонимом LEFT JOIN.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню