Jak uwzględnić wyniki „zero” / „0” w łącznej liczbie COUNT?

112

Po prostu trochę utknąłem w trochę SQL. Myślę, że nie potrafię genialnie sformułować tego pytania - więc pozwól, że ci pokażę.

Mam dwa stoliki, jeden na wezwanie, drugi na spotkanie. Próbuję zwrócić liczbę spotkań, które dana osoba ma (w tym jeśli ma zero). Termin zawiera person_idi jest person_idna spotkanie. Więc COUNT(person_id)jest to rozsądne podejście.

Zapytanie:

SELECT person_id, COUNT(person_id) AS "number_of_appointments" 
FROM appointment 
GROUP BY person_id;

Wróci poprawnie, liczba spotkań, które posiada person_id. Jednak osoba, która ma 0 spotkań, nie jest zwracana (oczywiście, ponieważ nie ma ich w tej tabeli).

Poprawienie instrukcji w celu pobrania identyfikatora osoby z tabeli osób daje mi coś takiego:

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;

To jednak nadal zwróci tylko osobę, która ma spotkanie, a nie to, czego chcę, czyli zwrot z osobami, które mają 0 spotkań!

Jakieś sugestie?

BrownE
źródło
1
A co jeśli chcę uzyskać zero | 0 jako wynik na pojedynczym stole. Mam tabelę vm_tool_licenses i zapytanie jest takie jak poniżej wybierz vm_tool_id, count (vm_tool_license_active) z grupy vm_tool_licenses przez vm_tool_license_active, vm_tool_id mając vm_tool_license_active = false`
Narendra

Odpowiedzi:

101

Potrzebujesz do tego sprzężenia zewnętrznego (i musisz użyć osoby jako tabeli „sterującej”)

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;

Powodem, dla którego to działa, jest to, że zewnętrzne (lewe) połączenie powróci NULLdla osób, które nie mają spotkania. Funkcja agregująca count()nie będzie liczyć NULLwartości, a zatem otrzymasz zero.

Jeśli chcesz dowiedzieć się więcej o złączeniach zewnętrznych, oto fajny samouczek: http://sqlzoo.net/wiki/Using_Null

koń bez imienia
źródło
ale co się stanie, jeśli niektóre pola spotkania NIE mają wartości NULL (w definicji tabeli)?
Lior Yehezkely
@LiorYehezkely: „niektóre kolumny” nie mają znaczenia. Funkcja count () używa kolumny łączenia. Jeśli to nie jest zerowe, oznacza to spotkanie, które należy policzyć
a_horse_with_no_name
21

Musisz użyć LEFT JOINzamiastINNER 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;
Hamlet Hakobyan
źródło
1
GROUP BY wygląda na literówkę w oryginalnym pytaniu, ponieważ tabela nie jest uwzględniona w zapytaniu.
Joachim Isaksson
7

jeśli wykonasz złączenie zewnętrzne (z liczbą), a następnie użyjesz tego wyniku jako tabeli podrzędnej, możesz uzyskać 0 zgodnie z oczekiwaniami (dzięki funkcji nvl)

Dawny:

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
Francois Mazet
źródło
5

UŻYJ sprzężenia, aby uzyskać 0 zliczenie w wyniku za pomocą GROUP BY.

po prostu „dołącz” powoduje złączenie wewnętrzne w MS SQL, więc wybierz złączenie lewe lub prawe.

Jeśli tabela zawierająca klucz podstawowy jest wymieniona jako pierwsza w ZAPYTANIU, użyj LEWEGO sprzężenia w przeciwnym razie PRAWEGO sprzężenia.

NA PRZYKŁAD:

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

Weź grupowanie z tabeli, która ma klucz podstawowy i policz od innej tabeli, która ma rzeczywiste wpisy / szczegóły.

Rohini CG
źródło
2

Aby zmienić jeszcze mniej w pierwotnym zapytaniu, możesz zmienić połączenie w RIGHTsprzężenie

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;

To po prostu opiera się na wybranej odpowiedzi, ale ponieważ sprzężenie zewnętrzne jest skierowane w RIGHTkierunku, wystarczy dodać tylko jedno słowo i mniej zmian. - Pamiętaj tylko, że jest tam i czasami może sprawić, że zapytania będą bardziej czytelne i wymagać mniej przebudowy.

sfj
źródło
0

Problem z LEFT JOIN polega na tym, że jeśli nie ma żadnych spotkań, nadal zwróci jeden wiersz z wartością zerową, która po zagregowaniu przez COUNT stanie się 1 i okaże się, że dana osoba ma jedno spotkanie, podczas gdy w rzeczywistości nie ma żadnego. Myślę, że to da prawidłowe wyniki:

SELECT person.person_id,
(SELECT COUNT(*) FROM appointment WHERE person.person_id = appointment.person_id) AS 'Appointments'
FROM person;
dannyw
źródło
Miałem zamiar opublikować to samo rozwiązanie, bardzo proste.
Joel