web-dev-qa-db-fra.com

Renvoie des lignes même si l'enregistrement n'existe pas LEFT OUTER JOIN

J'ai 2 tableaux ci-dessous:

Table_1
[Group No] [Test No] [Description]
123        1         [First Test]
123        2         [Second Test]
123        3         [Third Test]

Table_2
[Sample No] [Test No] [Result Description]
ABC         1         [Some More Result]
ABC         3         [Some Result]
DEF         1         [A Result]
DEF         2         [Results More]
DEF         3         [Bad Results]

Voici ma requête:

SELECT Table_1.[Group No], Table_1.[Test No], Table_1.Description, Table_2.[Result Description]
FROM Table_1 
LEFT OUTER JOIN Table_2 ON Table_1.[Test No] = Table_2.[Test No]
WHERE (Table_1.[Group No] = '123') AND (Table_2.[Sample No] = 'ABC')

la requête de djacobson:

SELECT Table_1.[Group No], Table_1.[Test No], Table_1.Description, Table_2.[Result Description]
FROM Table_1 
LEFT OUTER JOIN Table_2 ON Table_1.[Test No] = Table_2.[Test No]
WHERE (Table_1.[Group No] = '123') 
  AND (Table_2.[Sample No] IS NULL OR Table_2.[Sample No] = 'ABC')

Cela renvoie:

[Group No] [Test No] [Description] [Result Description]
123        1         [First Test]  [Some More Result]
123        3         [Third Test]  [Some Result]

Mais ce que je veux vraiment, c'est:

[Group No] [Test No] [Description] [Result Description]
123        1         [First Test]  [Some More Result]
123        2         [Second Test] NULL
123        3         [Third Test]  [Some Result]

Est-ce possible? Je voudrais retourner le dossier avec le test n ° 2. Cependant, comment puis-je rejoindre un dossier qui n'existe pas? Ou est-ce simplement impossible? Quelles sont les alternatives?

25
KayBee

Bien que vous utilisiez correctement une jointure externe, vous limitez ensuite l'ensemble de résultats aux cas où une valeur est présente dans Table_2 en incluant une colonne de cette table dans votre clause WHERE. Si vous voulez des enregistrements dont le numéro d'échantillon est ABC, OR il n'y a pas d'enregistrement dans Table_2, vous devez le faire:

SELECT Table_1.[Group No], Table_1.[Test No], Table_1.Description, Table_2.[Result Description]
FROM Table_1 
LEFT OUTER JOIN Table_2 ON Table_1.[Test No] = Table_2.[Test No]
WHERE (Table_1.[Group No] = '123') 
  AND (Table_2.[Sample No] IS NULL OR Table_2.[Sample No] = 'ABC')

Alternativement, vous pouvez filtrer les résultats de Table_2 lors de la jointure (qui, dans ce cas, se lit un peu plus proprement):

SELECT Table_1.[Group No], Table_1.[Test No], Table_1.Description, Table_2.[Result Description]
FROM Table_1 
LEFT OUTER JOIN Table_2 ON Table_1.[Test No] = Table_2.[Test No] AND Table_2.[Sample No] = 'ABC'
WHERE (Table_1.[Group No] = '123') 

Cela devrait accomplir la même chose. Le point important à retenir ici est que la clause WHERE filtre les résultats de la jointure de vos tables. Si vous utilisez des jointures externes mais souhaitez filtrer sur les tables jointes en externe, vous devez gérer le cas où aucun enregistrement n'existe de l'autre côté de la jointure.

43
Dan J