Domanda

Considera la seguente tabella:

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 |
+-------------+------+-----------+

Sto cercando di trovare quelle persone che hanno i telefoni di casa ma non le celle.

Questa query funziona:

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 |
+-------------+------+-----------+

ma questo non lo fa:

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 |
+-------------+------+-----------+

L'unica differenza tra i due è la posizione della condizione h.type = 'home' - nella prima è nella clausola where e nella seconda è parte della clausola on .

Perché la seconda query non restituisce lo stesso risultato della prima?

È stato utile?

Soluzione

Nel secondo SQL, la condizione h.type = 'home' fa parte delle condizioni del join esterno e non è un filtro sui risultati. Per tutti i record in cui h.type = 'cell', la condizione h.type = 'home' è FALSE e quindi non " matching " La riga c è stata trovata, quindi c.number è null, che è la tua unica condizione di filtro (WHERE).

In pseudo-codice il tuo secondo SQL funziona in questo modo:

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;

Altri suggerimenti

Quando faccio i join di sinistra, mi avvicino alle cose in questo modo. Nel join è necessario specificare i campi anny che collegano effettivamente le due tabelle insieme e qualsiasi condizione di filtro dal lato destro (seconda tabella nel join) del join (con un'eccezione, lo vedrò a breve). Le condizioni di filtro dal lato sinistro del join (1a tabella) dovrebbero trovarsi nella clausola where o influenzeranno erroneamente il join come hai visto (e come Tony ha spiegato così bene). L'unica volta che il lato destro del join dovrebbe trovarsi nella clausola where è se stai cercando valori null in quella tabella (ovvero, i record che si trovano nella prima tabella ma non nella seconda).

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')

Puoi provare questa domanda, spero che funzioni per te.

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

Non so se questo risolverà le cose o no, ma ...

Le istruzioni che iniziano con " e " dovrebbe essere parte della clausola WHERE, non parte della clausola ON. La clausola ON dovrebbe solo avere istruzioni che implicano quali colonne sono usate per unire le tabelle.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top