Warum werden NULL-Werte zuerst sortiert?

20

Warum werden die NULL-Werte zuerst sortiert, wenn wir einen NULL-Wert in einer Spalte haben und nach aufsteigendem Wert sortieren?

select 1 as test
union all
select 2
union all
select NULL
union all
select 3
union all
select 4
order by test

Ergebnisse in

NULL
1
2
3
4

Ich denke immer wieder, dass NULL "Unbestimmt" oder "Unbekannt" bedeutet. Wenn das wahr ist, würden sie dann nicht zuletzt sortieren, da der Wert größer sein könnte als alle anderen Werte? (Oder ist das irgendwo eine Sortieroption?)

Ich arbeite mit SQL Server 2008R2, aber ich vermute, dass dies für alle SQL Server und wahrscheinlich für alle RDBMS gilt.

Richard
quelle
1
Oracle listet es zuletzt auf. Das hat mich einmal durcheinander gebracht, weil ich dachte, es sollte sich wie SQL Server verhalten.
Andrei Rînea
2
Msgstr "Wenn das stimmt, würden sie nicht zuletzt sortieren, da der Wert größer sein könnte als alle anderen Werte". Der Wert kann auch kleiner als alle anderen Werte sein. Für mich ist es intuitiv, dass ein falscher Wert wie null am unteren Ende stehen sollte. Und praktisch, da Sie in der Praxis häufig die descBestellung verwenden möchten, um die größten oder neuesten Dinge zu zeigen. In diesem Fall wäre ich froh, wenn null Dinge die letzten wären.
Mahemoff
Die Datenbank macht das, was Sie ihm sagen. Wenn Sie wissen, dass Ihre Daten Nullen enthalten, und Sie geschäftliche Gründe haben, die Daten auf eine bestimmte Weise zu sortieren, müssen Sie dies entweder in der Abfrage oder in dem Code / der Ansicht angeben, der / die die Daten verarbeitet / anzeigt. Überlassen Sie das Sortieren niemals dem Standardverhalten der Datenbank.
nichts ist

Antworten:

19

BOL : Der Wert NULL gibt an, dass der Wert unbekannt ist. Ein Wert von NULL unterscheidet sich von einem leeren Wert oder einem Wert von Null. Keine zwei Nullwerte sind gleich. Vergleiche zwischen zwei Nullwerten oder zwischen einem NULL-Wert und einem beliebigen anderen Wert geben unknown zurück, da der Wert jedes NULL-Werts unbekannt ist.

NULL bedeutet unbekannt. Keine andere Interpretation ist gültig.

Wenn das wahr ist, würden sie dann nicht zuletzt sortieren, da der Wert größer sein könnte als alle anderen Werte?

Es gibt kein könnte sein . Es gibt keinen potenziellen Wert. Unbekannt ist unbekannt ist unbekannt.

Was den Grund angeht, warum es als erstes und nicht als letztes angezeigt wird, wird dies von veröffentlichten SQL-Standards nicht berücksichtigt und liegt leider im Ermessen des RDBMS-Anbieters:

Wikipedia : Der SQL-Standard definiert nicht explizit eine Standardsortierreihenfolge für Nullen. Stattdessen können auf konformen Systemen Nullen vor oder nach allen Datenwerten sortiert werden, indem die Klauseln NULLS FIRST bzw. NULLS LAST der ORDER BY-Liste verwendet werden. Nicht alle DBMS-Anbieter implementieren diese Funktionalität. Anbieter, die diese Funktionalität nicht implementieren, können unterschiedliche Behandlungen für die Nullsortierung im DBMS angeben.

Mark Storey-Smith
quelle
Es ist also ein Urteilsspruch. Das macht sehr viel Sinn. Vielen Dank!
Richard
6

Sie haben NULLRecht, dass dies "Unbestimmt" oder "Unbekannt" oder "Noch nicht bekannt" oder "Nicht zutreffend" bedeuten kann. Es gibt jedoch keinen Grund, die Nullen an die erste oder letzte Stelle zu setzen. Wenn wir die tatsächlichen Werte nicht kennen, können sie klein oder groß sein.

Ich denke, der Standard für die Bestimmung des gewünschten Verhaltens von Nullen während des Sortierens ist:

ORDER BY 
    test NULLS LAST                      --- or NULLS FIRST for the opposite

Leider hat SQL-Server diese Syntax noch nicht übernommen. Wenn ich mich nicht irre haben PostgreSQL und Oracle es.

Eine Lösung:

ORDER BY 
     CASE WHEN test IS NOT NULL 
            THEN 0 
          ELSE 1 
     END 
   , test

Eine andere Lösung, die abhängig vom Datentyp angepasst werden muss, aber keine gute Leistung bringt, da kein Index für Folgendes verwendet werden kann (test):

ORDER BY 
    COALESCE(test, 2147483647)               --- if it's a 4-byte signed integer
ypercubeᵀᴹ
quelle
Auf diese Weise kann der SQL-Server ORDER BY COALESCE (test, 2147483647) Index nicht verwenden.
Ardalan Shahgholi
3

Ich weiß nicht, warum es so gemacht wird, aber per Definition kann NULLS nicht mit Nicht-NULLS verglichen werden, daher müssen sie entweder am Anfang oder am Ende stehen (Marks Antwort behandelt dies ausführlicher).

So erhalten Sie das gewünschte Verhalten - Soweit ich weiß, gibt es keine Sortieroption, um Nullen als letzte zu setzen. Sie müssen es also umgehen, indem Sie eine berechnete Spalte verwenden, um sie als letzte zu erzwingen. In SQL Server können Sie jedoch nicht nach einer berechneten Spalte ( CASE WHEN ...) sortieren, wenn Ihre Daten einen festgelegten Operator ( UNION ALL) enthalten. So:

CREATE TABLE #sorttest(test int)
INSERT INTO #sorttest values(1)
INSERT INTO #sorttest values(5)
INSERT INTO #sorttest values(4)
INSERT INTO #sorttest values(NULL)
INSERT INTO #sorttest values(3)
INSERT INTO #sorttest values(2)
SELECT test
FROM #sorttest
ORDER BY CASE WHEN test IS NULL THEN 1 ELSE 0 END, test

DROP TABLE #sorttest

Funktioniert zum Sortieren von Nullen als letztes. Wenn Sie Ihren Datensatz mit UNION(oder EXCEPToder INTERSECTS) generieren müssen, geben Sie Ihre Daten wie oben beschrieben in eine temporäre Tabelle aus.

Simon Righarts
quelle
... oder verwenden Sie die UNIONed-Ausgabe als abgeleitete Tabelle.
Andriy M
0

Wenn Sie mit Zahlen zu tun haben, können Sie auch verwenden

ORDER BY -test DESC

NULLsind die niedrigstmöglichen Werte, DESCsetzen sie daher am Ende. Inzwischen haben die keine Nullwerte das Vorzeichen umgekehrt , so DESCtatsächlich eine ist ASCauf den realen Werten. Dies sollte schneller sein als CASEund ich nehme an, dass das Abfrageoptimierungsprogramm auch testSpaltenindizes verwenden kann.

Luca
quelle
3
Nein, es wäre nicht in der Lage, einen Index für die Sortierung zu verwenden. Es sei denn, Sie haben einen Index für den berechneten Ausdruck (- test).
Ypercubeᵀᴹ
1
Clever, wenn auch nur auf numerische Daten beschränkt (trotzdem für das OP-Beispiel geeignet). Ich bin mir nicht sicher, ob dies in der Tat schneller wäre als die Verwendung von CASE, aber ich bin mir sicher, dass es keinen Index verwenden würde (es sei denn, @ ypercubeᵀᴹ sagt - aber dann könnte ein CASE-Ausdruck genauso indiziert werden).
Andriy M