web-dev-qa-db-fra.com

Comment faire pour que SQL INNER JOIN accepte les résultats nuls

J'ai la requête suivante:

SELECT TOP 25 CLIENT_ID_MD5, COUNT(CLIENT_ID_MD5) TOTAL 
FROM dbo.amazonlogs 
GROUP BY CLIENT_ID_MD5 
ORDER BY COUNT(*) DESC;

Qui retourne:

283fe255cbc25c804eb0c05f84ee5d52    864458
879100cf8aa8b993a8c53f0137a3a176    126122
06c181de7f35ee039fec84579e82883d    88719
69ffb6c6fd5f52de0d5535ce56286671    68863
703441aa63c0ac1f39fe9e4a4cc8239a    47434
3fd023e7b2047e78c6742e2fc5b66fce    45350
a8b72ca65ba2440e8e4028a832ec2160    39524
...

Je veux récupérer le nom du client correspondant (FIRM) en utilisant le MD5 renvoyé de cette requête, donc une ligne pourrait ressembler à:

879100cf8aa8b993a8c53f0137a3a176    126122    Burger King

J'ai donc fait cette requête:

SELECT a.CLIENT_ID_MD5, COUNT(a.CLIENT_ID_MD5) TOTAL, c.FIRM 
FROM dbo.amazonlogs a 
  INNER JOIN dbo.customers c 
    ON c.CLIENT_ID_MD5 = a.CLIENT_ID_MD5
GROUP BY a.CLIENT_ID_MD5, c.FIRM 
ORDER BY COUNT(*) DESC;

Cela renvoie quelque chose comme:

879100cf8aa8b993a8c53f0137a3a176    126122    Burger King
06c181de7f35ee039fec84579e82883d    88719     McDonalds
703441aa63c0ac1f39fe9e4a4cc8239a    47434     Wendy's
3fd023e7b2047e78c6742e2fc5b66fce    45350     Tim Horton's

Ce qui fonctionne, sauf que je dois retourner une valeur vide pour c.FIRM s'il n'y a pas de FIRM correspondant pour un MD5 donné. Par exemple:

879100cf8aa8b993a8c53f0137a3a176    126122    Burger King
06c181de7f35ee039fec84579e82883d    88719     McDonalds
69ffb6c6fd5f52de0d5535ce56286671    68863
703441aa63c0ac1f39fe9e4a4cc8239a    47434     Wendy's
3fd023e7b2047e78c6742e2fc5b66fce    45350     Tim Horton's

Comment dois-je modifier la requête pour toujours renvoyer une ligne même s'il n'y a pas de c.FIRM correspondant?

32
Tom Redman

Remplacer INNER JOIN avec LEFT JOIN

104
evilone

utilisation LEFT JOIN au lieu de INNER JOIN

11
Punit

Une jointure interne exclut les valeurs NULL; vous voulez une jointure GAUCHE OUTER.

2
Joe

Au lieu de faire une jointure INNER, vous devez faire une jointure LEFT OUTER:

SELECT 
    a.CLIENT_ID_MD5, 
    COUNT(a.CLIENT_ID_MD5) TOTAL, 
    ISNULL(c.FIRM,'') 
FROM 
    dbo.amazonlogs a LEFT OUTER JOIN 
    dbo.customers c ON c.CLIENT_ID_MD5 = a.CLIENT_ID_MD5
GROUP BY 
    a.CLIENT_ID_MD5, 
    c.FIRM 
ORDER BY COUNT(0) DESC

http://www.w3schools.com/sql/sql_join.asp

2
Ian Nelson
SELECT a.CLIENT_ID_MD5, COUNT(a.CLIENT_ID_MD5) TOTAL, IsNull(c.FIRM, 'Unknown') as Firm
FROM dbo.amazonlogs a 
    LEFT JOIN dbo.customers c ON c.CLIENT_ID_MD5 = a.CLIENT_ID_MD5 
GROUP BY a.CLIENT_ID_MD5, c.FIRM ORDER BY COUNT(*) DESC; 

Cela vous donnera une valeur "Inconnu" lorsque les enregistrements dans la table des clients n'existent pas. Vous pouvez évidemment supprimer cette partie et simplement retourner c.FIRM si vous souhaitez avoir des valeurs nulles réelles à la place.

1
NotMe

Remplacez votre INNER JOIN par une OUTER JOIN ...

SELECT a.CLIENT_ID_MD5, COUNT(a.CLIENT_ID_MD5) TOTAL, c.FIRM
FROM dbo.amazonlogs a
LEFT OUTER JOIN dbo.customers c
  ON c.CLIENT_ID_MD5 = a.CLIENT_ID_MD5
GROUP BY a.CLIENT_ID_MD5, c.FIRM
ORDER BY COUNT(*) DESC;
1
mo.
WITH amazonlogs_Tallies
     AS
     (
      SELECT a.CLIENT_ID_MD5, COUNT(a.CLIENT_ID_MD5) TOTAL 
        FROM dbo.amazonlogs a 
       GROUP 
          BY a.CLIENT_ID_MD5 
     ), 
     amazonlogs_Tallies_Firms
     AS
     (
      SELECT a.CLIENT_ID_MD5, a.TOTAL, c.FIRM 
        FROM amazonlogs_Tallies a 
             INNER JOIN dbo.customers c 
                ON c.CLIENT_ID_MD5 = a.CLIENT_ID_MD5
     )
SELECT CLIENT_ID_MD5, TOTAL, FIRM
  FROM amazonlogs_Tallies_Firms
UNION 
SELECT CLIENT_ID_MD5, TOTAL, '{{NOT_KNOWN}}'
  FROM amazonlogs_Tallies
EXCEPT
SELECT CLIENT_ID_MD5, TOTAL, '{{NOT_KNOWN}}'
  FROM amazonlogs_Tallies_Firms;
1
onedaywhen