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.

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


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;

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


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

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

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

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.)


3
SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC

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

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


1

To działa dobrze:

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

position
1 
2
3
0
0

-8

Dlaczego nie zamawiasz przez NULLS LAST?

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.