2010-07-12 18 views
8

Tengo dos tablas. La Tabla A tiene una lista de nombres de empleados. La Tabla B es una tabla compleja con información sobre llamadas telefónicas realizadas por los empleados.SQL - Agrupar por con la combinación izquierda

Mi objetivo es hacer una tabla con las columnas 'name' y 'callCount'. Mi objetivo es hacer esto con un 'join' y un 'group by', pero sigo echando de menos a los empleados que no han hecho llamadas. ¿Cómo puedo mantener el nombre y poner un cero allí?

Quizás estoy cerca y alguien puede señalar mi error tipográfico? Gracias de antemano por su ayuda, aquí está el SQL:

SELECT A.name, COUNT(B.call_id) AS 'outgoing call count' 
FROM EmployeeTable A 
LEFT JOIN CallTable B 
ON A.name = B.call_from_name 
WHERE B.call_type LIKE 'outgoing' 
AND B.voice_mail = '0' 
... 
GROUP BY A.name 

Respuesta

25

Es un problema JOIN no nulo: su filtro está cambiando el EXTERIOR a una UNIÓN INTERNA. Esto significa que solo obtiene COUNT donde tiene filas en CallTable (B) en lugar de OUTER JOIN que deseaba.

SELECT A.name, COUNT(B.call_id) AS 'outgoing call count' 
FROM 
    EmployeeTable A 
    LEFT JOIN 
    (
    SELECT call_from_name, call_id FROM CallTable 
    WHERE call_type LIKE 'outgoing' 
    AND voice_mail = '0' 
    AND /* other CallTable filters */ 
    ) B 
    ON A.name = B.call_from_name 
WHERE 
    /* only EmployeeTable A filters */ 
GROUP BY A.name 

Editar: después de su comentario en otro lugar, todos los filtros en B debe estar en la tabla derivada, no en el exterior, donde.

+0

¡Maravilloso, muchas gracias! :) – Brandi

+3

Tenga cuidado al usar LIKE cuando no necesite las comparaciones de comodines. Realmente puede matar la velocidad de tu consulta. Solo haga una comparación de igualdad regular: DONDE call_type = 'saliente' –

+2

Para una explicación más detallada: http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN – HLGEM

2

Debido a que usted está utilizando una combinación izquierda, las referencias a la tabla definida en la combinación izquierda puede ser nulo. Las filas están ahí, no estás viendo el valor de recuento como cero. Lo que significa que es necesario convertir este valor NULL a cero (en este caso):

SELECT A.name, 
      COALESCE(COUNT(B.call_id), 0) AS 'outgoing call count' 
    FROM EmployeeTable A 
LEFT JOIN CallTable B ON B.call_from_name = A.name 
        AND B.call_type LIKE 'outgoing' 
        AND B.voice_mail = '0' 
    WHERE ... 
GROUP BY A.name 

este ejemplo se utiliza COALESCE, ANSI medio estándar de tratamiento de los valores NULL. Devolverá el primer valor no nulo, pero si no se encuentra ninguno, devolverá nulo. ISNULL es una alternativa válida en SQL Server, pero no es portátil para otras bases de datos mientras COALESCE lo es. Aquí está an MSDN article comparing the two functions.

+0

COALESCE no es necesario: es el filtro de la cláusula WHERE en B por lo que es una UNIÓN INTERNA – gbn

+0

He intentado ISNULL y COALESCE, ambos dan el mismo resultado. Puedo estar haciendo algo más mal? Tengo más cláusulas where de las que mencioné, pero todas son necesarias para determinar el recuento. – Brandi

Cuestiones relacionadas