Подсчет количества соединенных строк в левом соединении

Я пытаюсь написать сводный запрос в SQL, который возвращает количество всех записей, связанных с данной записью в таблице; Если к данной записи не были присоединены никакие записи, тогда результат для этой записи должен быть 0:

Данные

Моя база данных выглядит так (я не могу изменить структуру, к сожалению):

MESSAGE
----------------------------------------------
MESSAGEID   SENDER        SUBJECT
----------------------------------------------
1           Tim           Rabbit of Caerbannog
2           Bridgekeeper  Bridge of Death

MESSAGEPART
----------------------------------------------
MESSAGEID   PARTNO        CONTENT
----------------------------------------------
1           0             (BLOB)
1           1             (BLOB)
3           0             (BLOB)

(MESSAGEPART имеет составной PRIMARY KEY("MESSAGEID", "PARTNO"))

Желаемый выход

Учитывая приведенные выше данные, я должен получить примерно следующее:

MESSAGEID   COUNT(*)
-----------------------------------------------
1           2
2           0

Кажется очевидным, что мне нужно сделать левое соединение в таблице MESSAGE, но как мне вернуть счетчик 0 для строк, где объединенные столбцы из MESSAGEPART равны NULL? Я пробовал следующее:

Логика

Я пробовал

SELECT m.MESSAGEID, COUNT(*) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY m.MESSAGEID;

Однако это возвращает

MESSAGEID   COUNT(*)
-----------------------------------------------
1           2
2           1

Я также пробовал

SELECT mp.MESSAGEID, COUNT(*) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY mp.MESSAGEID;

но это возвращает

MESSAGEID   COUNT(*)
-----------------------------------------------
1           2
            1

Что я здесь делаю неправильно?

Ответы

Ответ 1

Как насчет чего-то вроде этого:

SELECT m.MESSAGEID, sum((case when mp.messageid is not null then 1 else 0 end)) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY m.MESSAGEID;

Функция COUNT() будет считать каждую строку, даже если она имеет значение null. Используя SUM() и CASE, вы можете считать только ненулевые значения.

EDIT: более простая версия, взятая из верхнего комментария:

SELECT m.MESSAGEID, COUNT(mp.MESSAGEID) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY m.MESSAGEID;

Надеюсь, что это поможет.

Ответ 2

Прежде чем присоединиться, вы сначала хотите считать в своей таблице messaepart, я думаю. Попробуйте следующее:

   SELECT m.MessageId
        , COALESCE(c, 0) as myCount
     FROM MESSAGE m
LEFT JOIN (SELECT MESSAGEID
                , count(*) c 
             FROM MESSAGEPART 
            GROUP BY MESSAGEID) mp
       ON mp.MESSAGEID = m.MESSAGEID

Ответ 3

Не забудьте использовать DISTINCT на тот случай, если вы ЛЕВЫЕ СОЕДИНИТЕ больше, чем одну таблицу:

SELECT m.MESSAGEID, COUNT(DISTINCT mp.MESSAGEID) FROM MESSAGE m
LEFT JOIN MESSAGEPART mp ON mp.MESSAGEID = m.MESSAGEID
GROUP BY m.MESSAGEID;