Pregunta

Considere la siguiente tabla:

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

Estoy tratando de encontrar a esas personas que tienen teléfonos de casa pero no celulares.

Esta consulta funciona:

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

pero este no:

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 única diferencia entre los dos es la ubicación de la condición h.type = 'home' : en el primero está en la cláusula where y en el segundo es parte de la cláusula on .

¿Por qué la segunda consulta no devuelve el mismo resultado que la primera?

¿Fue útil?

Solución

En el segundo SQL, la condición h.type = 'home' es parte de las condiciones de unión externa y no es un filtro en los resultados. Para todos los registros donde h.type = 'cell', la condición h.type = 'home' es FALSE y, por lo tanto, no '' coincidencia '' se encuentra la fila c, por lo que c.number es nulo, que es su única condición de filtrado (WHERE).

En pseudocódigo, su segundo SQL funciona así:

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;

Otros consejos

Cuando hago uniones izquierdas me acerco a las cosas de esta manera. En la combinación, debe especificar cualquier campo que realmente una las dos tablas y cualquier condición de filtrado desde el lado derecho (segunda tabla en la combinación) de la combinación (con una excepción, hablaré en breve). Las condiciones de filtrado desde el lado izquierdo de la unión (primera tabla) deben estar en la cláusula where o afectarán erróneamente la unión como viste (y como Tony explicó tan amablemente). La única vez que el lado derecho de la unión debe estar en la cláusula where si está buscando valores nulos en esa tabla (es decir, los registros que están en la primera tabla pero no en la segunda).

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

Puede probar esta consulta, espero que funcione para usted.

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

No sé si esto solucionará las cosas o no, pero ...

Las declaraciones que comienzan con " y " debe ser parte de la cláusula WHERE, no parte de la cláusula ON. La cláusula ON debería solo tener declaraciones que involucren qué columnas se usan para unir las tablas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top