2009-06-16 11 views
23

Ich erwarte das Ergebnis der dritten Abfrage unten enthalten ID = 732. Es tut es nicht. Warum das?MySQL SELECT x FROM ein WHERE NICHT IN (SELECT x FROM b) - Unerwartete Ergebnis

 
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) 

Es gibt drei NULL-Einträge in der Tabelle email.id und keine NULL-Einträge in der Datei match.id.

Die vollständige Tabelle/können Abfragen bei http://pastebin.ca/1462094

Antwort

39

Von documentation:

mit dem SQL Standard zu entsprechen, IN kehrt NULL nicht nur dann, wenn der Ausdruck auf der linken Seite ist NULL, aber auch, wenn keine Übereinstimmung in der Liste und einer der gefunden Ausdrücke in der Liste ist NULL.

Dies ist genau Ihr Fall.

Sowohl IN als auch NOT IN geben NULL zurück, was keine akzeptable Bedingung für WHERE Klausel ist.

Ihre Abfrage wie folgt umschreiben:

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

Ist es der Fall des OP? Mein Verständnis war, dass "wenn keine Übereinstimmung gefunden wird und einer der Ausdrücke in der Liste NULL ist" nicht der Fall ist, da 732 gefunden werden sollte, wodurch diese Klausel ungültig wird, richtig? – Eric

+0

@Eric: 732 wird nicht in E-Mails gefunden. – Quassnoi

+0

@Quassnoi: Du hast Recht, Gehirn-Lapsus :) – Eric

5

ich ein wenig mit den Einzelheiten, wie MySQL befasst sich mit NULL-Werte aus der Berührung bin zu sehen, aber hier ist, zwei Dinge zu versuchen:

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 

Die zweite Abfrage ist scheinbar intuitiv, aber sie führt die Join-Bedingung und dann die WHERE-Bedingung aus. Dies ist der Fall, wenn Joins und Where-Klauseln nicht gleichwertig sind.

+0

Mein Verständnis ist, dass die Verwendung einer linken Outer Join auch für die Leistung besser ist. –

31

... oder wenn Sie wirklich NOT IN verwenden möchten, können Sie

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

Dies funktionierte für mich, wollte ein Dropdown-Menü "Meter-Typen" erstellen, die nicht bereits ausgewählt wurde, dh hatte keine Datensätze in der zweiten Tabelle – zzapper

+1

Ich bevorzuge diese Antwort. Wusste nicht, dass "where id is not null null" notwendig war, um die "not in" -Abfrage funktionieren zu lassen. – marlar

-1

Hier einige SQL verwenden, die tatsächlich Sinn machen:

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

Einfach ist immer besser.

Verwandte Themen