質問
次の表を検討してください:
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 |
+-------------+------+-----------+
2つの唯一の違いは、h.type = 'home'
条件の場所です-最初の条件はwhere
句にあり、2番目の条件はon
句の一部です。
なぜ2番目のクエリが最初のクエリと同じ結果を返さないのですか?
解決
2番目のSQLでは、条件h.type = 'home'は外部結合条件の一部であり、結果のフィルターではありません。 h.type = 'cell'のすべてのレコードについて、条件h.type = 'home'はFALSEであるため、<!> quot; matching <!> quot; c行が見つかりました-したがって、c.numberはnullであり、これが唯一のフィルタリング(WHERE)条件です。
擬似コードでは、2番目の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;
他のヒント
左結合を行うとき、私は物事にこの方法でアプローチします。結合では、2つのテーブルを実際にリンクするannyフィールドと、結合の右側(結合の2番目のテーブル)からのフィルター条件を指定する必要があります(1つの例外を除いて、すぐに説明します)。 join(1st table)の左側からのフィルタリング条件はwhere句にあるべきです。さもないと、見たように(そしてTonyがうまく説明したように)結合に誤って影響します。結合の右側がwhere句にあるのは、そのテーブル(つまり、最初のテーブルにあるが2番目のテーブルにはないレコード)でnull値を探している場合だけです。
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')
これで問題が解決するかどうかはわかりませんが、...
<!> quot;および<!> quotで始まるステートメント。 ON句の一部ではなく、WHERE句の一部である必要があります。 ON句には、テーブルを結合するために使用される列に関係するステートメントを only だけ含める必要があります。