MySQL Ordina un numero, per ultimo Nulls


280

Attualmente sto facendo un OrderBy di base nella mia dichiarazione.

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

Il problema è che le voci NULL per 'position' sono trattate come 0. Pertanto tutte le voci con posizione come NULL appaiono prima di quelle con 1,2,3,4. per esempio:

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

C'è un modo per ottenere il seguente ordine:

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

8
È necessario riconsiderare la risposta dell'utente user1052645. È più semplice, non richiede alcuna conoscenza dei valori massimi e potrebbe essere più veloce (supponendo che la valutazione di un'espressione possa essere più veloce di una chiamata di funzione).
Steve Clay,

Risposte:


568

MySQL ha una sintassi non documentata per ordinare gli null per ultimi. Posizionare un segno meno (-) prima del nome della colonna e passare da ASC a DESC:

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

È essenzialmente il position DESCcontrario di posizionare i valori NULL per ultimi, ma altrimenti uguale a position ASC.

Un buon riferimento è qui http://troels.arvin.dk/db/rdbms#select-order_by


79
Non è privo di documenti, - col_nameè un'espressione ( 0 - col_name), che accetta la clausola ORDER BY. Naturalmente questo funziona solo per colonne numeriche.
Steve Clay,

7
Ben fatto. Funziona anche per datee timecolonne! (MySQL 5.5). Immagino (sono pigro da controllare) funziona per tutte le colonne simili a numeri (timestamp, float ...).
Martin,

6
@koral: è un'espressione matematica semplice (e utile) che inverte l'ordine, non verrà rimosso a meno che la lingua stessa non cambi radicalmente.
Bell

11
Come suggeriscono i commenti, funziona per colonne numeriche, di data e ora? Ma che dire di varchar? Può essere applicato anche per varchar? Ho provato ad applicarlo ai campi varchar, ma l'ordine sembra essere diverso dall'uso di ASC o DESC.
Sumit Desai,

9
Ciò non impedirà l'utilizzo di un possibile indice nell'ordine per colonna?
Tarsis,

306

Ho trovato che questa è una buona soluzione per la maggior parte:

SELECT * FROM table ORDER BY ISNULL(field), field ASC;

6
Senza ridefinire l'ordine per opere: SELECT * FROM table ORDER BY ISNULL(field) ASC;(MySQL 5.5)
Marçal Juan

5
Questa è una soluzione migliore
Rok Kralj,

4
La soluzione accettata non funziona con TIMESTAMP in postgresql 9.3. Questa soluzione fa ...
kalu,

2
Stranamente, MySQL non utilizzerà un indice sul campo quando aggiungi isnull (campo) alla clausola order by (quando usi il limite).
Barry Kelly,

3
@kalu: In PostgreSQL , i valori NULL sono ordinati per ultimi in ordine crescente (e per primi in ordine decrescente). E preferiresti usare la clausola SQL standardNULLS LAST | NULLS FIRSTper capovolgerlo invece delle soluzioni alternative qui.
Erwin Brandstetter,

23

Qualcosa di simile a

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

Sostituisci 999999999 con qualunque sia il valore massimo per il campo


3
Questa soluzione è fragile e può portare a bug intermittenti
Dmitry Bogdanovich

20

ULTIMO NULL

SELECT * FROM table_name ORDER BY id IS NULL, id ASC

4

Puoi scambiare istanze di NULL con un valore diverso per ordinarle prima (come 0 o -1) o per ultimo (un numero grande o una lettera) ...

SELECT field1, IF(field2 IS NULL, 9999, field2) as ordered_field2
  FROM tablename
 WHERE visible = 1
 ORDER BY ordered_field2 ASC, id DESC

Ciò non risolverà il problema poiché l'indice a cui si fa riferimento in ORDER BY non sarà influenzato dalla sostituzione dei valori nell'istruzione SELECT e pertanto non correggerà l'ordinamento. Inoltre, controlla la funzione COALESCE, che è funzionalmente equivalente all'uso della funzione IF.
definisce il

Se si alias l'istruzione IF correttamente, le righe vengono ordinate come previsto. Ho risolto il mio esempio.
Langdon,

4

Prova a usare questa query:

SELECT * FROM tablename
WHERE visible=1 
ORDER BY 
CASE WHEN position IS NULL THEN 1 ELSE 0 END ASC,id DESC

Non è necessario il caso. IS NULL restituisce 1 quando espressione è NULL. Vedi la risposta di riverbero.
contactmatt

3

Puoi unire i tuoi NULL nell'istruzione ORDER BY:

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

Se si desidera ordinare i NULL in basso, provare coalesce(position, 100000). (Rendi il secondo numero più grande di tutti gli altri positionnel db.)


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

6
Perché l'OP dovrebbe provare questo ? Le buone risposte avranno sempre una spiegazione di ciò che è stato fatto e del perché sia ​​stato fatto in questo modo, non solo per l'OP ma anche per i futuri visitatori di SO che potrebbero trovare questa domanda e leggere la tua risposta.
RiggsFolly,

2

Per una DATEcolonna puoi usare:


NULL ultimo:

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

Gli spazi vuoti durano:

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

1

Per ottenere il seguente risultato:

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

Usa la sintassi, posiziona -(minus sign)prima del nome del campo e usa il tipo di ordine inverso (come: se vuoi l'ordine per ordine ASC, usa DESC o se vuoi l'ordine DESC, usa ASC)

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


1

Funziona benissimo:

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

position
1 
2
3
0
0

-8

Perché non ordini da NULLS LAST?

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

NULLS LAST- quale versione di MySQL è stata introdotta?
crmpicco,

2
@Panique, vuoi dire (MS) SQL Server?
d -_- b

1
questa risposta non si applica a MySQL
PeppyHeppy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.