MySQL Orderby eine Zahl, Nullen zuletzt

279

Derzeit mache ich eine sehr einfache OrderBy in meiner Erklärung.

SELECT * FROM tablename WHERE visible=1 ORDER BY position ASC, id DESC

Das Problem dabei ist, dass NULL-Einträge für 'Position' als 0 behandelt werden. Daher erscheinen alle Einträge mit Position als NULL vor denen mit 1,2,3,4. z.B:

NULL, NULL, NULL, 1, 2, 3, 4

Gibt es eine Möglichkeit, die folgende Reihenfolge zu erreichen:

1, 2, 3, 4, NULL, NULL, NULL.
JonB
quelle
8
Sie sollten die Antwort von user1052645 überdenken. Es ist einfacher, erfordert keine Kenntnis der Maximalwerte und kann schneller sein (vorausgesetzt, die Auswertung eines Ausdrucks ist möglicherweise schneller als ein Funktionsaufruf).
Steve Clay

Antworten:

566

MySQL hat eine undokumentierte Syntax, um Nullen zuletzt zu sortieren. Setzen Sie ein Minuszeichen (-) vor den Spaltennamen und schalten Sie den ASC auf DESC:

SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC, id DESC

Es ist im Wesentlichen die Umkehrung der position DESCPlatzierung der NULL-Werte als letztes, aber ansonsten dasselbe als position ASC.

Eine gute Referenz finden Sie hier http://troels.arvin.dk/db/rdbms#select-order_by

Erschüttert
quelle
79
Es ist nicht undokumentiert, - col_nameist ein Ausdruck ( 0 - col_name), den die ORDER BY-Klausel akzeptiert. Dies funktioniert natürlich nur für numerische Spalten.
Steve Clay
7
Schön. Funktioniert auch für dateund timeSpalten! (MySQL 5.5). Ich denke (ich bin faul zu überprüfen), dass es für alle zahlenähnlichen Spalten (Zeitstempel, Float ...) funktioniert.
Martin
6
@koral: Es ist ein einfacher (und nützlicher) mathematischer Ausdruck, der die Reihenfolge umkehrt. Er wird nur entfernt, wenn sich die Sprache selbst dramatisch ändert.
Bell
11
Wie aus den Kommentaren hervorgeht, funktioniert es für numerische, Datums- und Zeitspalten? Aber was ist mit Varchar? Kann es auch für Varchar angewendet werden? Ich habe versucht, es auf Varchar-Felder anzuwenden, aber die Reihenfolge scheint sich von der Verwendung von ASC oder DESC zu unterscheiden.
Sumit Desai
9
Verhindert dies nicht die Verwendung eines möglichen Index für die Reihenfolge nach Spalten?
Tarsis
305

Ich fand das größtenteils eine gute Lösung:

SELECT * FROM table ORDER BY ISNULL(field), field ASC;
d -_- b
quelle
6
Ohne die Reihenfolge durch Werke neu zu definieren: SELECT * FROM table ORDER BY ISNULL(field) ASC;(MySQL 5.5)
Marçal Juan
5
Dies ist eine bessere Lösung.
Rok Kralj
4
Die akzeptierte Lösung funktioniert nicht mit TIMESTAMP in postgresql 9.3. Diese Lösung tut ...
kalu
2
Ärgerlicherweise verwendet MySQL keinen Index für das Feld, wenn Sie der order by-Klausel isnull (Feld) hinzufügen (wenn Sie limit verwenden).
Barry Kelly
3
@kalu: In PostgreSQL werden NULL-Werte zuletzt in aufsteigender Reihenfolge (und zuerst in absteigender Reihenfolge) sortiert . Und Sie möchten lieber die Standard-SQL- Klausel NULLS LAST| verwenden NULLS FIRSTum es anstelle der Problemumgehungen hier umzudrehen.
Erwin Brandstetter
23

Etwas wie

SELECT * FROM tablename where visible=1 ORDER BY COALESCE(position, 999999999) ASC, id DESC

Ersetzen Sie 999999999 durch den Maximalwert für das Feld

DrewM
quelle
3
Diese Lösung ist zerbrechlich und kann zu zeitweiligen Fehlern führen
Dmitry Bogdanovich
20

NULL LETZT

SELECT * FROM table_name ORDER BY id IS NULL, id ASC
sumeet
quelle
4

Sie können Instanzen von NULL gegen einen anderen Wert austauschen, um sie zuerst (wie 0 oder -1) oder zuletzt (eine große Zahl oder ein Buchstabe) zu sortieren ...

SELECT field1, IF(field2 IS NULL, 9999, field2) as ordered_field2
  FROM tablename
 WHERE visible = 1
 ORDER BY ordered_field2 ASC, id DESC
Langdon
quelle
Dies löst das Problem nicht, da der in ORDER BY referenzierte Index nicht durch das Ersetzen von Werten in der SELECT-Anweisung beeinflusst wird und dadurch die Reihenfolge nicht korrigiert wird. Überprüfen Sie auch die COALESCE-Funktion, die funktional Ihrer Verwendung der IF-Funktion entspricht.
Definiert den
Wenn Sie die IF-Anweisung richtig aliasen, werden die Zeilen wie erwartet sortiert. Ich habe mein Beispiel korrigiert.
Langdon
4

Versuchen Sie es mit dieser Abfrage:

SELECT * FROM tablename
WHERE visible=1 
ORDER BY 
CASE WHEN position IS NULL THEN 1 ELSE 0 END ASC,id DESC
Rachit Patel
quelle
Keine Notwendigkeit für Fall. IS NULL gibt 1 zurück, wenn der Ausdruck NULL ist. Siehe die Antwort von Reverbnation.
Kontaktmatt
3

Sie können sich verbinden Ihre NULLs in der ORDER BYAussage:

select * from tablename
where <conditions>
order by
    coalesce(position, 0) ASC, 
    id DESC

Wenn Sie möchten, dass die NULL-Werte unten sortiert werden, versuchen Sie es coalesce(position, 100000). (Machen Sie die zweite Zahl größer als alle anderen positionin der Datenbank.)

Seth
quelle
3
SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC
YasirPoongadan
quelle
6
Warum sollte das OP dies versuchen ? Gute Antworten enthalten immer eine Erklärung darüber, was getan wurde und warum dies so getan wurde, nicht nur für das OP, sondern auch für zukünftige Besucher von SO, die diese Frage möglicherweise finden und Ihre Antwort lesen.
RiggsFolly
2

Für eine DATESpalte können Sie verwenden:


NULL zuletzt:

ORDER BY IFNULL(`myDate`, '9999-12-31') ASC

Leerzeichen zuletzt:

ORDER BY IF(`myDate` = '', '9999-12-31', `myDate`) ASC
Danny Beckett
quelle
1

Um folgendes Ergebnis zu erzielen:

1, 2, 3, 4, NULL, NULL, NULL.

-(minus sign)Verwenden Sie die Syntax, setzen Sie sie vor den Feldnamen und verwenden Sie inverse order_type (wie: Wenn Sie nach ASC-Reihenfolge bestellen möchten, verwenden Sie DESC oder wenn Sie DESC-Reihenfolge möchten, verwenden Sie ASC)

SELECT * FROM tablename WHERE visible=1 ORDER BY -position DESC

Nishu Garg
quelle
1

Das funktioniert gut:

SELECT * FROM tablename ORDER BY position = 0, position ASC;

position
1 
2
3
0
0
voxl.de
quelle
-8

Warum bestellen Sie nicht bei NULLS LAST?

SELECT * 
FROM tablename
WHERE visible = 1 
ORDER BY position ASC NULLS LAST, id DESC 
RedRover
quelle
NULLS LAST- Welche Version von MySQL wurde eingeführt?
Crmpicco
2
@Panique, du meinst (MS) SQL Server?
d -_- b
1
Diese Antwort gilt nicht für MySQL
PeppyHeppy