2010-07-12 11 views
8

J'ai deux tables. Le tableau A contient une liste de noms d'employés. Le tableau B est un tableau complexe contenant des informations sur les appels téléphoniques effectués par les employés.SQL - Grouper avec Left Join

Mon but est de faire une table avec les colonnes 'name' et 'callCount'. Je vise à faire cela avec une «gauche de joint» et un «groupe par», mais je continue à manquer les employés qui n'ont fait aucun appel. Comment puis-je l'obtenir pour garder le nom et juste mettre un zéro là? Peut-être que je suis proche et quelqu'un peut signaler ma faute de frappe? Merci d'avance pour votre aide, voici le 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 

Répondre

25

C'est un problème JOIN pas un NULL: votre filtre est en train de changer le OUTER à un INNER JOIN. Cela signifie que vous obtenez seulement COUNT où vous avez des lignes dans CallTable (B) plutôt que l'OUTER JOIN que vous vouliez.

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 

Edit: après votre commentaire ailleurs, tous vos filtres B doit être à la table dérivée, pas dans l'extérieur où.

+0

Merveilleux, merci beaucoup! :) – Brandi

+3

Faites attention à utiliser LIKE lorsque vous n'avez pas besoin des comparaisons génériques. Il peut vraiment tuer votre vitesse de requête. Faites juste une comparaison d'égalité régulière: OERE call_type = 'sortant' –

+2

Pour plus d'explications: http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN – HLGEM

2

Parce que vous utilisez un LEFT JOIN, les références à la table définies dans le LEFT JOIN peut être nul. Les lignes sont là, vous ne voyez simplement pas la valeur de compte comme zéro. Ce qui signifie que vous avez besoin de convertir cette valeur NULL à zéro (dans ce cas):

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 

Cet exemple utilise COALESCE, un moyen standard ANSI de la gestion des valeurs NULL. Il retournera la première valeur non nulle, mais si aucun ne peut être trouvé, il retournera null. ISNULL est une alternative valide sur SQL Server, mais n'est pas portable vers d'autres bases de données alors que COALESCE l'est. Voici .

+0

COALESCE non nécessaire: c'est le filtre de clause WHERE sur B qui en fait un INNER JOIN – gbn

+0

J'ai essayé ISNULL et COALESCE, tous deux donnent le même résultat. Je peux faire quelque chose d'autre? J'ai plus de clauses que celles que j'ai énumérées, mais elles sont toutes nécessaires pour déterminer le nombre. – Brandi