Pergunta

Considere a tabela a seguir:

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

Eu estou tentando encontrar aquelas pessoas que têm telefones de casa, mas não células.

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

mas este não faz:

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

A única diferença entre os dois é a localização da condição h.type = 'home' -. No primeiro é na cláusula where e no segundo, de parte da cláusula on

Por que não a segunda consulta devolver o mesmo resultado que o primeiro?

Foi útil?

Solução

Na segunda SQL, a condição h.type = 'casa' faz parte da associação externa condições, e não é um filtro nos resultados. Para todos os registros onde h.type = 'célula', o h.type condição = 'casa' é falso e assim não há "matching" linha C é encontrada - assim c.number é nulo, que é o seu (WHERE) condição só filtrando .

Em pseudo-código seu segundo SQL funciona assim:

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;

Outras dicas

Ao fazer esquerda junta-se me aproximo as coisas desta maneira. No juntar-se você precisa especificar anny campos que realmente ligam as duas tabelas juntos e qualquer condição de filtragem do lado direito (2ª tabela na junção) da junção (com uma exceção, eu vou chegar em breve). Filtrando condições do lado esquerdo do join (1º quadro) deve ser na cláusula WHERE ou eles vão afetar de forma errada a se juntar como você viu (e como Tony tão bem explicado). A única vez que o lado direito da junção deve estar na cláusula onde é que se você estiver procurando por valores nulos na tabela (ou seja, os registros que estão na primeira mesa, mas não o segundo).

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

Você pode tentar esta consulta, eu espero que ele vai trabalhar para você.

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

Eu não sei se isso vai consertar as coisas ou não, mas ...

As afirmações começando com "e" deve ser parte da cláusula WHERE, não faz parte da cláusula ON. A cláusula ON devem única tem declarações que envolvem as colunas que são usados ??para unir as tabelas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top