Подсчет количества соединенных строк в левом соединении
Я пытаюсь написать сводный запрос в 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;