SQL-Server: Warum liefert der Vergleich null=Wert true zurück, für NICHT?
Warum spielt der Vergleich von value
zu null
false zurück, außer bei Verwendung eines NOT IN
, wo gibt es true zurück?
Gegeben, eine Abfrage aller stackoverflow-Benutzer, die haben post:
SELECT * FROM Users
WHERE UserID IN (SELECT UserID FROM Posts)
Diese wie erwartet funktioniert; bekomme ich eine Liste aller Benutzer, die ein post.
Nun die Abfrage für die inverse, finden Sie alle stackoverflow-Benutzer, die nicht post:
SELECT * FROM Users
WHERE UserID NOT IN (SELECT UserID FROM Posts)
Diesem keine Datensätze zurückgibt, was falsch ist.
Gegeben hypothetischen 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...
... ...
Übernehmen und die Regeln des Null-Werte:
NULL = NULL
mit unknown ausgewertetNULL <> NULL
mit unknown ausgewertetvalue = NULL
wertet unbekannt
Wenn wir uns auf die 2. Abfrage, die uns interessiert, findet alle Zeilen, in denen die Benutzer.UserID ist nicht gefunden in den Beiträgen.UserID-Spalte. ich würde gehen logischerweise wie folgt:
Check UserID 1
1 = 1
gibt true zurück. So können wir daraus folgern, dass dieser Benutzer hat einige posts, und schließen Sie Sie nicht in die Ausgabe-Liste
Überprüfen Sie nun, UserID, 2:
2 = 1
gibt false zurück, so halten wir auf der Suche2 = 2
gibt true zurück, so können wir daraus folgern, dass dieser Benutzer hat einige posts, und schließen Sie Sie nicht in die Ausgabe-Liste
Überprüfen Sie nun, UserID 399573
399573 = 1
gibt false zurück, so halten wir auf der Suche399573 = 2
gibt false zurück, so halten wir auf der Suche- ...
399573 = null
gibt unbekannt ist, so halten wir auf der Suche- ...
Wir fanden keine Beiträge UserID 399573, so würden wir mit ihm in der output-Liste.
Außer SQL Server dies nicht tut. Wenn Sie eine NULL in Ihrem in
Liste, dann plötzlich, es findet eine übereinstimmung. Es plötzlich eine übereinstimmung findet. Plötzlich 399573 = null
zu true ausgewertet wird.
Warum spielt der Vergleich von value
zu null
Rückkehr unbekannt, außer, wenn es zurück wahr?
Bearbeiten: ich weiß, dass ich dies umgehen unsinnig Verhalten unter Ausschluss der null-Werte:
SELECT * FROM Users
WHERE UserID NOT IN (
SELECT UserID FROM Posts
WHERE UserID IS NOT NULL)
Aber ich sollte nicht zu haben, soweit ich das sagen kann, der booleschen Logik sollte in Ordnung sein, ohne Sie - daher meine Frage.
Fußnoten
- 1 hypothetische Daten; wenn Sie es nicht mögen: machen Sie Ihr nach unten.
- celko hat nun seinen eigenen tag
- Duplizieren: Siehe stackoverflow.com/questions/129077/...
- ich sehe. Es ist nicht darauf hingewiesen die andere Frage - aber es ist ein bug, wie die
NOT IN
erweitert wird. Anstatt logisch zu bestimmen, ob die Zeile "nicht in" die Liste, es erweitert es um eine Reihe vonand <>
Klauseln. - Boyd = ich denke nicht, dass das ein bug ist. Etwas anderes zu erinnern ist
IN
verwendetor
undNOT IN
verwendetAND
. Wenn Sie die Auswertung gegen eineNULL
mit eine Ungleichheit im Vergleich zu einem bekannten Wert, bekommen Sie immer falsch, da es keine Möglichkeit gibt zu wissen, ob es passt oder nicht. - Boyd: ich würde nicht nennen dies ein Fehler.
IN
ist nichts mehr als eine praktische Abkürzung für eine Reihe vonOR
Klauseln. Technisch gesehen, der richtige Weg zu denken, der ausbau in die andere Frage ist:select 'true' where NOT(3 = 1 or 3 = 2 or 3 = null)
, das ist logisch äquivalent von DeMorgan ' s Law. In jedem Fall, der Trugschluss ist die Annahme, dass ein Vergleich von einem Wert=NULL Wert FALSE zurück, wenn in der Tat das Ergebnis UNBEKANNT ist. - Yep. Kein Fehler ist. Auch ist es nicht booleschen Logik. Es ist 3 bewertet logic.
- Joe Stefanelli: das ist das problem. Konvertieren
IN
zuor
, undNOT IN
zuand
ändert sich die logische Bedeutung. - Boyd - Nein, logisch eine Liste von Werten für eine
IN
Klausel SOLLTE sich die Evaluierung auf eine Reihe vonOR
Aussagen. DieNOT IN
auch logisch ausgewertet, um eine Serie vonAND
Aussagen. Was fragst du, wenn du fragst, ob ein WertNOT IN (a,b,c,d)
als zu sagen, es istNOT a, NOT b, NOT c, AND ALSO NOT d
? - "ich denke über das naming meiner Tochter Kirsten, aber nur, wenn keiner meiner Freunde haben eine Schwester mit dem Namen Kirsten. Die Namen von mein Freund der Schwestern sind:
Nicholle
,Joanne
ich nicht, habe eine Schwester,Sherry
. Ausgezeichnete,Kirsten
istnot in
die Liste der Namen. Einige math-geek drehte es in der booleschen algebra wird die falsche Antwort, dann sagt er, dass die Frage selbst ist fehlerhaft. Das ist in Ordnung, aber Fragen Sie irgendjemanden, der Abschluss der 8. Klasse, welche Antwort richtig ist. Aber egal: ich habe die Antwort auf meine Frage:NOT IN
bedeutet nichtNOT IN
es bedeutetand <> ... and <> ... and <>
. - Betrachten Sie auch den Algorithmus, den ich in der ursprünglichen Frage zu bewerten
NOT IN
- das ist das, was jeder vernünftige Mensch tun würde, wenn gefragt wird, obKirsten
ist nicht in (Nicholle
,Joanne
ich nicht, habe eine Schwester,Sherry
). Datenbank-engine Designer wählte darstellenNOT IN
alsand <> and <> and <>
, was in Ordnung ist. - Stefanelli "ist nichts weiter als eine praktische Abkürzung für etwas anderes. Meine Verwirrung war, dass ich dachte
not in
gemeintnot in
ich wusste nicht, es war eine Abkürzung für eine Reihe vonand <>
. Einmal definiert wurde: die Ergebnisse, die ich sehen, macht Sinn. - Boyd - Für Ihre Schwester-name-Problem, das ist eine Daten-Modellierung Problem. Sie sollten über eine Untertabelle
SISTER
bezieht sich Sie zurück zu Ihrem Haupt-Tabelle. Wenn Sie nicht eine Schwester haben, Sie wäre nicht in die Ergebnismenge aufgenommen. AuchNULL
bedeutet unbekannt. Wenn Sie haben 2 Leute, deren Namen Sie nicht kennen, können Sie sagen Ihre Namen nicht, Kirsten? - Du denkst wie ein computer-Wissenschaftler, die das Gegenteil von dem ein normaler Mensch.
- Boyd - Deine Schwester z.B. würde so funktionieren, wie Sie erwarten, wenn Sie eine nicht-ANSI-null-Wert, wie eine leere Zeichenfolge (als dummy-null-Wert, nicht wirklich null ist)--oder ausschalten ANSI_NULLS -, natürlich. Aber dein Beispiel ist auch nicht voraussehen, mehrere Schwestern (ich bin mir nicht sicher, ob das Modell vorgeschlagen von @JNK nicht, entweder). Wenn Sie eine Zeile für jede Schwester mit einem fremden Schlüssel zurück an den entsprechenden Freund finde ich die entsprechende Abfrage, die Sie würde dann-Konstrukt mit einem INNER JOIN korrekt, ignorieren Sie Freunde mit keine Schwestern und produzieren die richtige Liste mit Namen die keine null-Werte in es.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Häufiges problem, Konserven Antwort:
Das Verhalten des NICHT-IN-Klausel kann verwirrend sein und als solche braucht es einige Erklärungen. Betrachten Sie die folgende Abfrage:
Obwohl es mehr als tausend verschiedene Nachnamen in AdventureWorks.Person.Kontaktieren Sie die Abfrage nichts zurückgibt. Das sieht vielleicht nicht besonders intuitiv für einen Anfänger, Datenbank-Programmierer, aber es macht tatsächlich auch Sinn. Die Erklärung besteht aus mehreren einfachen Schritten. Überlegen Sie zuerst, die folgenden zwei Abfragen, die eindeutig sind äquivalent:
Beachten Sie, dass beide Abfragen die erwarteten Ergebnisse zurück. Nun, erinnern wir uns an DeMorgan ' s theorem, welches besagt, dass:
Bin ich Ausschneiden und einfügen aus Wikipedia (http://en.wikipedia.org/wiki/De_Morgan_duality). Anwendung von DeMorgan ' s theorem auf diese Abfragen, daraus folgt, dass diese beiden Abfragen sind ebenfalls äquivalent:
Diese Letzte Nachname<>NULL kann nie wahr sein
not (unknown or true) = false
, aber(not unknown) and (not true) = unknown
ist, verletzt das theoremNOT IN
ist definiert als ein alias für(x<>a) AND (x<>b) AND (x<>c) ...
.Der Annahme in deinem ersten Satz ist nicht richtig:
Aber der Vergleich einen Wert null nicht zurück
false
; es gibtunknown
. Undunknown
hat seine eigene Logik:Einem Beispiel, wie dies funktioniert:
Den
where
Klausel nur Spiele auftrue
, so dass diese Filter, die aus jeder Zeile.Finden Sie die volle Pracht der 3-Wert-Logik bei Wikipedia.
AND null
zu bewerten, zuunknown
. Frage steht immer noch.