Question

Considérez le tableau suivant:

mysql> select * from phone_numbers;
+-------------+------+-----------+
| number      | type | person_id |
+-------------+------+-----------+
| 17182225465 | home |         1 |
| 19172225465 | cell |         1 |
| 12129876543 | home |         2 |
| 13049876543 | cell |         2 |
| 15064223454 | home |         3 |
| 15064223454 | cell |         3 |
| 18724356798 | home |         4 |
| 19174335465 | cell |         5 |
+-------------+------+-----------+

J'essaie de trouver ces personnes qui ont un téléphone à la maison mais pas de cellules.

Cette requête fonctionne:

mysql> select h.*
    -> from phone_numbers h
    -> left join phone_numbers c
    -> on h.person_id = c.person_id
    -> and c.type = 'cell'
    -> where h.type = 'home'
    -> and c.number is null;
+-------------+------+-----------+
| number      | type | person_id |
+-------------+------+-----------+
| 18724356798 | home |         4 |
+-------------+------+-----------+

mais celui-ci ne le fait pas:

mysql> select h.*
    -> from phone_numbers h
    -> left join phone_numbers c
    -> on h.person_id = c.person_id
    -> and h.type = 'home'
    -> and c.type = 'cell'
    -> where c.number is null;
+-------------+------+-----------+
| number      | type | person_id |
+-------------+------+-----------+
| 19172225465 | cell |         1 |
| 13049876543 | cell |         2 |
| 15064223454 | cell |         3 |
| 18724356798 | home |         4 |
| 19174335465 | cell |         5 |
+-------------+------+-----------+

La seule différence entre les deux réside dans l'emplacement de la condition h.type = 'home' . Dans le premier cas, il se trouve dans la clause et dans le second, partie de la clause on .

Pourquoi la deuxième requête ne donne-t-elle pas le même résultat que la première?

Était-ce utile?

La solution

Dans le second code SQL, la condition h.type = 'home' fait partie des conditions de jointure externe et ne constitue pas un filtre sur les résultats. Pour tous les enregistrements où h.type = 'cell', la condition h.type = 'home' est FALSE et, par conséquent, pas de "correspondance". c row est trouvé - c.number est donc null, ce qui est votre seule condition de filtrage (WHERE).

En pseudo-code, votre deuxième code SQL fonctionne comme suit:

for each row in phone_numbers h /* Note this is ALL home AND cell phones */
   select c.number from phone_numbers c
   where h.person_id = c.person_id
   and h.type = 'home'
   and c.type = 'cell';
   if c.number is null (i.e. no row found)
     display h.*
   end if
end loop;

Autres conseils

Lorsque je fais des jointures à gauche, j’aborde les choses de cette façon. Dans la jointure, vous devez spécifier des champs anny qui relient effectivement les deux tables et toute condition de filtrage du côté droit (2ème table de la jointure) de la jointure (à une exception près, je vais en arriver à bientôt). Les conditions de filtrage du côté gauche de la jointure (1ère table) doivent être dans la clause where ou elles affecteront à tort la jointure, comme vous l'avez vu (et comme Tony l'a si bien expliqué). Le seul moment où le côté droit de la jointure doit figurer dans la clause where est si vous recherchez des valeurs null dans cette table (c'est-à-dire, les enregistrements qui se trouvent dans la première table mais pas dans la seconde).

SEL * 
FROM phone_numbers T1
WHERE typeS='home' AND person_id NOT IN
(SELECT person_id FROM phone_numbers  T2 WHERE T1.person_id=T2.person_id AND  typeS='cell')

Vous pouvez essayer cette requête, j'espère que cela fonctionnera pour vous.

select * from phone_numbers
where person_id not in (select person_id from phone_numbers where type='cell')

Je ne sais pas si cela va régler le problème ou pas, mais ...

Les déclarations commençant par "&"; devrait faire partie de la clause WHERE, pas de la clause ON. La clause ON doit seulement contenir des instructions concernant les colonnes utilisées pour joindre les tables.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top