문제
다음 표를 고려하십시오.
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 |
+-------------+------+-----------+
나는 홈 전화를 가지고 있지만 휴대폰을 가지고 있지 않은 사람들을 찾으려고 노력하고 있습니다.
이 쿼리는 작동합니다.
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 |
+-------------+------+-----------+
그러나 이것은 그렇지 않습니다.
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 |
+-------------+------+-----------+
둘 사이의 유일한 차이점은 h.type = 'home'
조건 - 처음에는 그 안에 있습니다 where
절과 두 번째는 on
절.
두 번째 쿼리가 첫 번째 결과와 동일한 결과를 반환하지 않는 이유는 무엇입니까?
해결책
두 번째 SQL에서 조건 h.type = 'home'은 외부 조정 조건의 일부이며 결과에 대한 필터가 아닙니다. h.type = 'cell'이있는 모든 레코드의 경우, 조건 h.type = 'home'은 거짓이므로 "일치하는"C 행이 발견되지 않으므로 C.Number는 유일한 필터링 (위치) 조건입니다. .
의사 코드에서 두 번째 SQL은 다음과 같이 작동합니다.
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;
다른 팁
왼쪽에 합류 할 때 나는 이런 식으로 접근합니다. Join에서는 실제로 두 테이블을 실제로 연결하는 Anny 필드와 오른쪽의 필터링 조건 (Join의 두 번째 테이블)을 지정해야합니다 (한 가지 예외적으로, 곧 도달하겠습니다). 조인의 왼쪽에서 필터링 조건 (첫 번째 테이블)은 Where 절에 있어야합니다. 그렇지 않으면 Tony가 본 것처럼 조인에 잘못 영향을 미칩니다 (Tony가 너무 멋지게 설명 된대로). 가입의 오른쪽이 해당 테이블에서 널 값을 찾는 경우 (즉, 첫 번째 테이블에 있지만 두 번째 표에있는 레코드).
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')
이 쿼리를 시도해 볼 수 있습니다. 그것이 당신에게 효과가 있기를 바랍니다.
select * from phone_numbers
where person_id not in (select person_id from phone_numbers where type='cell')
이것이 문제를 해결할 것인지 모르겠지만 ...
"및" "로 시작하는 진술은 ON 절의 일부가 아니라 WHERE 절의 일부 여야합니다. ON 절은해야합니다 뿐 테이블에 결합하는 데 사용되는 열과 관련된 진술이 있습니다.