2014-08-28 2 views
6

Ich habe zwei Tabellen:Warum ruft IN nicht immer dieselben Ergebnisse wie MINUS in Oracle ab?

CREATE TABLE test1 
(id int); 

CREATE TABLE test2 
(id int); 

INSERT INTO test1 
VALUES (1); 

INSERT INTO test1 
VALUES (2); 

INSERT INTO test2 
VALUES (1); 

Dann möchte ich eine Liste aller IDs sehen, die in test1 sind und nicht in test2.

Es gibt mindestens drei Möglichkeiten, wie ich denken kann, dies zu tun:

OUTER JOIN:

SELECT a.id 
FROM test1 a LEFT OUTER JOIN test2 b 
ON a.id = b.id 
WHERE b.id IS NULL; 

MINUS:

SELECT id 
FROM test1 
MINUS 
SELECT id 
FROM test2; 

NICHT IN:

So weit, so gut. Alle drei dieser Abfragen sollten mir die gleichen Ergebnisse geben: 1 Zeile mit dem Wert 2.

Wenn ich eine Null in Test2 einfügen, dann die OUTER JOIN und MINUS Abfragen weiterhin die gleichen Ergebnisse, aber die NOT IN bringt keine Zeilen zurück.

Das hat mich sehr verwirrt. Ich bemerkte dann, dass, wenn ich es zu

SELECT id 
FROM test1 
WHERE id NOT IN (
       SELECT id 
       FROM test2 
       WHERE id IS NOT NULL 
       ); 

änderte, dass ich die Ergebnisse erhalte, die ich erwartete - eine Reihe wieder.

Warum tritt dies auf? Ich gehe davon aus, dass dies etwas fundamentales für SQL ist, aber ich weiß nicht, was es ist (und ich bin ziemlich sicher, dass in anderen Datenbanken, die ich bereits erwähnt habe, gleichwertige Ergebnisse erzielt haben - obwohl ich nicht Habe jetzt keinen SQL Server oder Postgres zum Testen, daher kann ich mich über ihr Verhalten ärgern.

(Ich nehme an, eine Antwort darauf lautet: "Mach dir keine Sorgen, und benutze NOT IN nicht"), aber das kann in Bezug auf die Lesbarkeit von Code teuer sein - manchmal ist das eleganter als alles mit Outer Joins oder Minus.

+1

"etwas ziemlich fundamental zu SQL": Definitiv. 'NULL' macht dir in Vergleichen nie gut. 'NULL' ist weder gleich noch ungleich zu irgendetwas, nicht einmal sich selbst. – Thilo

+2

null ist kein Wert, aber ein unbekannter –

Antwort

3

Wenn NULL im NOT IN Zustand ist, dann wird das Ergebnis immer NULL sein.

id NOT IN (a, b, c) 

ist die gleiche wie:

id != a AND id != b AND id != c 

Alles vergleichen mit NULL mit !=, wird das Ergebnis NULL, so dass Sie leer Ergebnis bekam.


id IN (a, b, c) 

ist die gleiche wie

id = a OR id = b OR id = c 

, nicht wahr?

Also !(id = a OR id = b OR id = c) ist id != a AND id != b AND id != c.

+3

'<>' ist SQL-Standard, aber die Antwort ist wahr :) –

+0

Können Sie teilen, wo Sie gefunden haben, dass 'NICHT IN (a, b, c) ist gleich wie: ID! = a UND id! = b UND id! = c' – cha

+0

@cha Siehe meine Bearbeitung. – xdazz

Verwandte Themen