web-dev-qa-db-fra.com

MySQL a quitté la jointure externe avec la clause where - retourne des lignes sans correspondance

J'ai deux tableaux: pq et pe. J'essaie de LEFT OUTER JOIN tableau de gauche (pq) sur le tableau de droite (pe).

  • pq a une colonne de clé primaire id
  • pe a une clé primaire à deux colonnes, il peut donc avoir plusieurs pqid ou aucun
  • pe. La colonne uid doit être utilisée pour extraire uniquement les données pertinentes (WHERE pe.uid = "12345")
  • pe. les données doivent être jointes à chaque pq. id ligne

Voici à quoi ressemblent les tableaux:

pq:
id | data
1  | "abc"
2  | "efg"

pe:
pqid | uid   | data
2    | 54321 | "uvw"
2    | 12345 | "xyz"

Je peux utiliser la requête suivante pour faire correspondre les 2 premières lignes de pq. Id à pe. Pqid

SELECT pq.id, pq.data, pe.data FROM pq
    LEFT OUTER JOIN pe ON pq.id = pe.pqid
    ORDER BY pq.id LIMIT 2

Je reçois:

pq.id | pq.data |  pe.data
1     | "abc"   |  
2     | "efg"   |  "uvw"

Mais si j'utilise l'instruction WHERE comme ceci:

SELECT pq.id, pq.data, pe.data FROM pq
    LEFT OUTER JOIN pe ON pq.id = pe.pqid
    WHERE pe.uid='12345'
    ORDER BY pq.id LIMIT 2

Je ne reçois qu'une seule ligne avec la correspondance pe. Pqid ET pe. Uid:

pq.id | pq.data |  pe.data
2     | "efg"   |  "xyz"

Donc, avec la clause WHERE, j'obtiens les bonnes données pe., Mais pas pq les lignes qui n'ont pas pq. Id matching - pe. pqid

Je dois obtenir ceci:

pq.id | pq.data |  pe.data
1     | "abc"   |  
2     | "efg"   |  "xyz"
15
Xeos

Oui. La clause where transforme la jointure externe gauche en jointure interne.

Pourquoi? La valeur de pe.pqid est NULL (tout comme pe.uid) lorsqu'il n'y a pas de correspondance. La comparaison dans la clause where échoue donc (presque toutes les comparaisons avec NULL renvoient NULL qui est considérée comme fausse).

La solution consiste à déplacer la comparaison vers la clause on:

SELECT pq.id, pq.data, pe.data
FROM pq LEFT OUTER JOIN
     pe
     ON pq.id = pe.pqid and
        pe.uid='12345'
ORDER BY pq.id LIMIT 2
40
Gordon Linoff