Как включить "нулевой" / "0" результат в агрегат COUNT?
Я только что немного застрял с некоторым SQL. Я не думаю, что я могу сформулировать этот вопрос блестяще - так позвольте мне показать вам.
У меня есть две таблицы, одна называется человеком, одна называется назначением. Я пытаюсь вернуть количество назначений, которые у человека есть (в том числе, если они имеют нуль). Назначение содержит person_id
, и для каждой встречи есть person_id
. Итак, COUNT(person_id)
- разумный подход.
Запрос:
SELECT person_id, COUNT(person_id) AS "number_of_appointments"
FROM appointment
GROUP BY person_id;
Вернется правильно, количество назначений person_id. Тем не менее, человек, у которого есть 0 встреч, не возвращается (очевидно, поскольку они не находятся в этой таблице).
Тонкая настройка для принятия person_id из таблицы персонажей дает мне что-то вроде:
SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM appointment
JOIN person ON person.person_id = appointment.person_id
GROUP BY person.person_id;
Это, однако, все равно вернет person_id, у которого назначена встреча, а не то, что я хочу, это возвращение с людьми, у которых есть 0 встреч!
Любые предложения, пожалуйста?
Ответы
Ответ 1
Вам нужно внешнее соединение для этого (и вам нужно использовать человека как таблицу "вождения" )
SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM person
LEFT JOIN appointment ON person.person_id = appointment.person_id
GROUP BY person.person_id;
Причина, по которой это работает, заключается в том, что внешнее (левое) соединение вернет NULL
для тех лиц, у которых нет встречи. Агрегатная функция count()
не будет считать значения NULL
, и вы получите нуль.
Если вы хотите узнать больше о внешних соединениях, вот хороший учебник: http://sqlzoo.net/wiki/Using_Null
Ответ 2
Вы должны использовать LEFT JOIN
вместо INNER JOIN
SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM person
LEFT JOIN appointment ON person.person_id = appointment.person_id
GROUP BY person.person_id;
Ответ 3
если вы выполняете внешнее соединение (со счетчиком), а затем используете этот результат в качестве подкатегории, вы можете получить 0, как ожидалось (благодаря функции nvl)
Пример:
select P.person_id, nvl(A.nb_apptmts, 0) from
(SELECT person.person_id
FROM person) P
LEFT JOIN
(select person_id, count(*) as nb_apptmts
from appointment
group by person_id) A
ON P.person_id = A.person_id
Ответ 4
USE join, чтобы получить 0 счет в результате с помощью GROUP BY.
просто "join" делает внутреннее соединение в MS SQL, поэтому, Go для левого или правого соединения.
Если таблица, содержащая первичный ключ, упоминается сначала в QUERY, тогда используйте LEFT join else RIGHT join.
EG:
select WARDNO,count(WARDCODE) from MAIPADH
right join MSWARDH on MSWARDH.WARDNO= MAIPADH.WARDCODE
group by WARDNO
.
select WARDNO,count(WARDCODE) from MSWARDH
left join MAIPADH on MSWARDH.WARDNO= MAIPADH.WARDCODE group by WARDNO
Возьмите группу из таблицы, которая имеет первичный ключ и подсчет из другой таблицы, которая имеет фактические записи/детали.
Ответ 5
Чтобы еще меньше изменить исходный запрос, вы можете превратить свое объединение в объединение RIGHT
SELECT person.person_id, COUNT(appointment.person_id) AS "number_of_appointments"
FROM appointment
RIGHT JOIN person ON person.person_id = appointment.person_id
GROUP BY person.person_id;
Это только основывается на выбранном ответе, но поскольку внешнее объединение находится в направлении RIGHT
, необходимо добавить только одно слово и меньше изменений. - Просто помните, что он там и иногда может сделать запросы более читабельными и потребовать меньше перестройки.
Ответ 6
Проблема с LEFT JOIN состоит в том, что, если нет встреч, он все равно вернет одну строку с нулем, который при агрегировании COUNT станет 1, и будет казаться, что у человека есть одна встреча, когда на самом деле его нет. Я думаю, что это даст правильные результаты:
SELECT person.person_id,
(SELECT COUNT(*) FROM appointment WHERE person.person_id = appointment.person_id) AS 'Appointments'
FROM person;