2009-06-16 8 views
23

私は、以下の3番目のクエリの結果にid = 732が含まれることを期待しています。それはしません。何故ですか?MySQL SELECT xはどこからではない(SELECT x FROM b) - 予期しない結果

 
mysql> SELECT id FROM match ORDER BY id DESC LIMIT 5 ; 
+------------+ 
|   id | 
+------------+ 
|  732 | 
|  730 | 
|  655 | 
|  458 | 
|  456 | 
+------------+ 
5 rows in set (0.00 sec) 

mysql> SELECT id FROM email ORDER BY id DESC LIMIT 5 ; 
+------------+ 
|   id | 
+------------+ 
|  731 | 
|  727 | 
|  725 | 
|  724 | 
|  723 | 
+------------+ 
5 rows in set (0.00 sec) 

mysql> SELECT * FROM match WHERE id NOT IN (SELECT id FROM email) ; 
Empty set (0.00 sec) 

テーブルemail.idには3つのNULLエントリがあり、match.idにはNULLエントリはありません。

フルテーブル/クエリが、私は少しMySQLはヌルを扱うが、ここでは試して二つのことだ方法の詳細とタッチの外だhttp://pastebin.ca/1462094

答えて

39

SQL規格に準拠するため、IN戻りNULLだけでなく、左側の式がNULL、だけでなく、一致がリストに見つからない場合とのいずれかである場合リスト内の式はNULLです。

これはまさにあなたのケースです。

INNOT IN return NULLのいずれも、WHERE節のための条件ではありません。次のように

は、クエリを書き直し

SELECT * 
FROM match m 
WHERE NOT EXISTS 
     (
     SELECT 1 
     FROM email e 
     WHERE e.id = m.id 
     ) 
+0

OPのケースですか?私の理解は、 "一致が見つからず、リスト内の式の1つがNULLである場合" 732が見つかるはずなので、その句を無効にする必要があるということです。 – Eric

+0

@Eric:732はメールに見つかりません。 – Quassnoi

+0

@Quassnoi:そうだよ、脳死: – Eric

5

で見ることができます。

SELECT * FROM match WHERE id NOT IN 
    (SELECT id FROM email WHERE id IS NOT NULL) ; 

SELECT 
    m.* 
FROM 
    match m 
    LEFT OUTER JOIN email e ON 
     m.id = e.id 
     AND e.id IS NOT NULL 
WHERE 
    e.id IS NULL 

2番目のクエリは直感的に見えますが、結合条件を実行してからwhere条件を実行します。これは、結合とwhere節が等価でない場合です。 documentationから

+0

私の理解では、パフォーマンスの面でも左外部結合を使用する方が良いということです。 –

31

を...またはあなたが本当に

SELECT * FROM match WHERE id NOT IN (SELECT id FROM email WHERE id IS NOT NULL) 
+0

これは私のために働いていて、まだ選択されていない「メータータイプ」のドロップダウンを作成したかった。つまり、第2テーブルのレコードがなかった。 – zzapper

+1

「not in」クエリを動作させるには、「id is null nullでない」ということを知らなかった。 – marlar

-1

を使用することができますNOT IN使用したい場合はここで実際に意味をなすいくつかのSQLです:

は、
SELECT m.id FROM match m LEFT JOIN email e ON e.id = m.id WHERE e.id IS NULL 

シンプルで常に優れています。

関連する問題