SQL Server: Warum gibt der Vergleich null = value für NOT IN true zurück?
Warum macht der Vergleich vonvalue
zunull
return false, außer bei Verwendung einesNOT IN
, wo es wahr zurückgibt?
Gab eine Abfrage, um alle Stackoverflow-Benutzer zu finden, diehabe Ein Eintrag
SELECT * FROM Users
WHERE UserID IN (SELECT UserID FROM Posts)
Dies funktioniert wie erwartet; Ich bekomme eine Liste aller Benutzer, die einen Beitrag haben.
Now Abfrage für die Umkehrung; Finde alle Stackoverflow-Benutzer, die nicht Habe einen Beitrag:
SELECT * FROM Users
WHERE UserID NOT IN (SELECT UserID FROM Posts)
Dies gibt keine Datensätze zurück, was falsch ist.
Gegeben hypothetische Daten1
Users Posts
================ ===============================
UserID Username PostID UserID Subject
------ -------- ------- ------ ----------------
1 atkins 1 1 Welcome to stack ov...
2 joels 2 2 Welcome all!
... ... ... ...
399573 gt6989b ... ...
... ... ... ...
10592 null (deleted by nsl&fbi...
... ...
Und nimm die Regeln von NULL an:
NULL = NULL
ergibt unbekanntesNULL <> NULL
ergibt unbekanntesvalue = NULL
wertet unbekannt ausWenn wir uns die 2. Abfrage ansehen, sind wir daran interessiert, alle Zeilen zu finden, in denen die Users.UserID @ isnich in der Spalte Posts.UserID gefunden. Ich würde logischerweise wie folgt vorgehen:
Check UserID 1
1 = 1
gibt true zurück. Daraus schließen wir, dass dieser Benutzer einige Posts hat und diese nicht in die Ausgabeliste @ einschließJetzt UserID 2 prüfen:
2 = 1
gibt false zurück, also suchen wir weiter2 = 2
gibt true zurück, sodass wir zu dem Schluss kommen, dass dieser Benutzer einige Posts hat und diese nicht in die Ausgabeliste einbezieht.Jetzt UserID 399573 prüfen
399573 = 1
gibt false zurück, also suchen wir weiter399573 = 2
gibt false zurück, also suchen wir weiter ...399573 = null
gibt unbekannt zurück, also suchen wir weiter ...Wir haben keine Beiträge von UserID 399573 gefunden, daher würden wir ihn in die Ausgabeliste aufnehmen.
Except SQL Server tut dies nicht. Wenn Sie eine NULL in Ihrem @ habin
Liste, dann plötzlich findet es eine Übereinstimmung.Es findet plötzlich eine Übereinstimmung. Plötzlich399573 = null
ergibt true.
Warum macht der Vergleich vonvalue
zunull
return unbekannt, außer wenn es true zurückgibt?
Bearbeite: Ich weiß, dass ich dieses @ umgehen kaunsinni Verhalten durch spezielles Ausschließen der Nullen:
SELECT * FROM Users
WHERE UserID NOT IN (
SELECT UserID FROM Posts
WHERE UserID IS NOT NULL)
Aber ich sollte nicht müssen, soweit ich sagen kann, dass die boolesche Logik ohne sie in Ordnung sein sollte - daher meine Frage.
Fußnoten1 hypothetische Daten; wenn es dir nicht gefällt: mach dein unten wieder gut.celko hat jetzt seinen eigenen Tag