MySQL Po numerze, Nulls last

280

Obecnie wykonuję bardzo proste OrderBy w moim oświadczeniu.

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

Problem polega na tym, że wpisy NULL dla „pozycji” są traktowane jako 0. Dlatego wszystkie wpisy z pozycją NULL pojawiają się przed tymi z 1,2,3,4. na przykład:

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

Czy istnieje sposób na uzyskanie następującej kolejności:

1, 2, 3, 4, NULL, NULL, NULL.
JonB
źródło
8
Powinieneś ponownie rozważyć odpowiedź użytkownika 1052645. Jest to prostsze, nie wymaga znajomości maksymalnych wartości i może być szybsze (zakładając, że ocena wyrażenia może być szybsza niż wywołanie funkcji).
Steve Clay,

Odpowiedzi:

567

MySQL ma nieudokumentowaną składnię do sortowania wartości zerowych na końcu. Umieść znak minus (-) przed nazwą kolumny i przełącz ASC na DESC:

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

Jest to zasadniczo odwrotność position DESCumieszczania wartości NULL na końcu, ale poza tym taka sama jak position ASC.

Dobry odnośnik znajduje się tutaj http://troels.arvin.dk/db/rdbms#select-order_by

Jarred
źródło
79
Nie jest nieudokumentowane, - col_namejest wyrażeniem ( 0 - col_name), które akceptuje klauzula ORDER BY. Oczywiście działa to tylko w przypadku kolumn numerycznych.
Steve Clay,
7
Niezłe. Roboty datei timekolumny też! (MySQL 5.5). Chyba (jestem leniwy, aby sprawdzić) to działa dla wszystkich kolumn podobnych do liczb (znacznik czasu, liczba zmiennoprzecinkowa ...).
Martin
6
@koral: jest to proste (i przydatne) wyrażenie matematyczne, które odwraca kolejność, nie zostanie usunięte, chyba że sam język dramatycznie się zmieni.
Bell
11
Jak sugerują komentarze, działa w przypadku kolumn numerycznych, daty i godziny? Ale co z varcharem? Czy można go stosować również do varchar? Próbowałem zastosować go do pól varchar, ale kolejność wydaje się inna niż przy użyciu ASC lub DESC.
Sumit Desai
9
Czy nie zapobiegnie to wykorzystaniu możliwego indeksu przy zamówieniu według kolumny?
Tarsis
305

Uważam, że jest to dobre rozwiązanie w przeważającej części:

SELECT * FROM table ORDER BY ISNULL(field), field ASC;
d -_- b
źródło
6
Bez redefiniowania kolejności prac: SELECT * FROM table ORDER BY ISNULL(field) ASC;(MySQL 5.5)
Marçal Juan
5
To lepsze rozwiązanie.
Rok Kralj
4
Zaakceptowane rozwiązanie nie działa z TIMESTAMP w postgresql 9.3. To rozwiązanie nie ...
kalu
2
Irytujące jest to, że MySQL nie użyje indeksu na polu, gdy dodasz isnull (pole) do zamówienia według klauzuli (przy użyciu limitu).
Barry Kelly,
3
@kalu: W PostgreSQL wartości NULL są sortowane na końcu w kolejności rosnącej (i najpierw w kolejności malejącej). I wolisz użyć standardowej klauzuli SQLNULLS LAST | NULLS FIRSTodwrócić to zamiast obejść tutaj.
Erwin Brandstetter,
23

Coś jak

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

Zamień 999999999 na dowolną maksymalną wartość dla tego pola

DrewM
źródło
3
To rozwiązanie jest kruche i może prowadzić do sporadycznych błędów
Dmitrij Bogdanowicz
20

NULL LAST

SELECT * FROM table_name ORDER BY id IS NULL, id ASC
sumeet
źródło
4

Możesz zamienić wystąpienia NULL z inną wartością, aby posortować je najpierw (np. 0 lub -1) lub ostatnie (duża liczba lub litera) ...

SELECT field1, IF(field2 IS NULL, 9999, field2) as ordered_field2
  FROM tablename
 WHERE visible = 1
 ORDER BY ordered_field2 ASC, id DESC
Langdon
źródło
Nie rozwiąże to problemu, ponieważ zastąpienie wartości w instrukcji SELECT nie będzie miało wpływu na indeks wymieniony w ORDER BY, a tym samym nie poprawi kolejności. Sprawdź także funkcję COALESCE, która jest funkcjonalnie równoważna z użyciem funkcji IF.
określa
Jeśli poprawnie aliasujesz instrukcję IF, wiersze zostaną uporządkowane zgodnie z oczekiwaniami. Naprawiłem mój przykład.
Langdon,
4

Spróbuj użyć tego zapytania:

SELECT * FROM tablename
WHERE visible=1 
ORDER BY 
CASE WHEN position IS NULL THEN 1 ELSE 0 END ASC,id DESC
Rachit Patel
źródło
Nie potrzeba skrzynki. IS NULL zwraca 1, gdy wyrażenie ma wartość NULL. Zobacz odpowiedź pogłosu.
contactmatt
3

Możesz połączyć swoje wartości NULL w ORDER BYzestawieniu:

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

Jeśli chcesz, aby wartości NULL były sortowane na dole, spróbuj coalesce(position, 100000). (Zrób drugą liczbę większą niż wszystkie inne positionw db.)

Seth
źródło
3
SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC
YasirPongongadan
źródło
6
Dlaczego PO powinien tego próbować ? Dobre odpowiedzi zawsze będą wyjaśniać, co zostało zrobione i dlaczego zostało zrobione w ten sposób, nie tylko dla PO, ale dla przyszłych gości SO, którzy mogą znaleźć to pytanie i przeczytać twoją odpowiedź.
RiggsFolly
2

Do DATEkolumny możesz użyć:


NULLS ostatnie:

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

Ostatnie puste miejsca:

ORDER BY IF(`myDate` = '', '9999-12-31', `myDate`) ASC
Danny Beckett
źródło
1

Aby osiągnąć następujący wynik:

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

UŻYJ składni, umieść -(minus sign)przed nazwą pola i użyj odwrotnego typu_pole (np .: jeśli chcesz zamówić według kolejności ASC, użyj DESC lub jeśli chcesz zamówić DESC, użyj ASC)

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

Nishu Garg
źródło
1

To działa dobrze:

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

position
1 
2
3
0
0
voxl.de
źródło
-8

Dlaczego nie zamawiasz przez NULLS LAST?

SELECT * 
FROM tablename
WHERE visible = 1 
ORDER BY position ASC NULLS LAST, id DESC 
RedRover
źródło
NULLS LAST- jaką wersję MySQL wprowadzono?
crmpicco
2
@Panique, masz na myśli (MS) SQL Server?
d -_- b
1
ta odpowiedź nie dotyczy MySQL
PeppyHeppy