¿Cómo incluir resultados "cero" / "0" en COUNT agregado?

112

Me he quedado un poco atascado con algo de SQL. No creo que pueda formular la pregunta de manera brillante, así que déjame mostrarte.

Tengo dos mesas, una llamada persona, otra llamada cita. Estoy intentando devolver la cantidad de citas que tiene una persona (incluso si tienen cero). La cita contiene el person_idy hay una person_idpor cita. Entonces COUNT(person_id)es un enfoque sensato.

La consulta:

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

Devolverá correctamente, la cantidad de citas que tiene un person_id. Sin embargo, una persona que tiene 0 citas no se devuelve (obviamente, ya que no está en esa tabla).

Ajustar la declaración para tomar person_id de la tabla de personas me da algo como:

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;

Sin embargo, esto solo devolverá un person_id que tiene una cita y no lo que quiero, que es una devolución con personas que tienen 0 citas.

¿Alguna sugerencia por favor?

MarrónE
fuente
1
¿Qué pasa si quiero obtener cero? 0 como resultado en una sola tabla. Tengo la tabla vm_tool_licenses y la consulta es la siguiente, seleccione vm_tool_id, cuente (vm_tool_license_active) del grupo vm_tool_licenses por vm_tool_license_active, vm_tool_id teniendo vm_tool_license_active = false`
Narendra

Respuestas:

101

Quieres una combinación externa para esto (y necesitas usar person como la tabla "conductora")

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;

La razón por la que esto está funcionando es que la unión externa (izquierda) regresará NULLpara aquellas personas que no tengan una cita. La función agregada count()no contará NULLvalores y, por lo tanto, obtendrá un cero.

Si desea obtener más información sobre las combinaciones externas, aquí hay un buen tutorial: http://sqlzoo.net/wiki/Using_Null

un caballo sin nombre
fuente
pero ¿qué pasa si algunos de los campos de la cita NO son NULL (en la definición de la tabla)?
Lior Yehezkely
@LiorYehezkely: "algunas de las columnas" no importa. Count () usa la columna de unión. Si eso no es nulo, entonces hay una cita que debe contarse
a_horse_with_no_name
21

Debes usar en LEFT JOINlugar deINNER 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 Akobian
fuente
1
GROUP BY parece un error tipográfico en la pregunta original, ya que la tabla no está incluida en la consulta.
Joachim Isaksson
7

si realiza la combinación externa (con el recuento) y luego usa este resultado como una subtabla, puede obtener 0 como se esperaba (gracias a la función nvl)

Ex:

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
fuente
5

USE join para obtener 0 recuento en el resultado usando GROUP BY.

simplemente 'unirse' hace que Inner se una en MS SQL, así que vaya a la unión izquierda o derecha.

Si la tabla que contiene la clave principal se menciona primero en la CONSULTA, utilice la combinación IZQUIERDA o la combinación DERECHA.

P.EJ:

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

Tome el grupo de la tabla que tiene la clave principal y cuente de la otra tabla que tenga entradas / detalles reales.

Rohini CG
fuente
2

Para cambiar aún menos en su consulta original, puede convertir su combinación en una RIGHTcombinación

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;

Esto solo se basa en la respuesta seleccionada, pero como la combinación externa está en la RIGHTdirección, solo se debe agregar una palabra y menos cambios. - Recuerde que está ahí y, a veces, puede hacer que las consultas sean más legibles y requieran menos reconstrucción.

sfj
fuente
0

El problema con LEFT JOIN es que si no hay citas, todavía devolverá una fila con un nulo, que cuando se agregue por COUNT se convertirá en 1, y parecerá que la persona tiene una cita cuando en realidad no tiene ninguna. Creo que esto dará los resultados correctos:

SELECT person.person_id,
(SELECT COUNT(*) FROM appointment WHERE person.person_id = appointment.person_id) AS 'Appointments'
FROM person;
dannyw
fuente
Solo iba a publicar esta misma solución, muy simple.
Joel