Как включить "нулевой" / "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;