MySQL Ordenar por un número, Nulos últimos

280

Actualmente estoy haciendo un OrderBy muy básico en mi declaración.

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

El problema con esto es que las entradas NULL para 'posición' se tratan como 0. Por lo tanto, todas las entradas con posición como NULL aparecen antes que aquellas con 1,2,3,4. p.ej:

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

¿Hay alguna manera de lograr el siguiente orden:

1, 2, 3, 4, NULL, NULL, NULL.
JonB
fuente
8
Debería reconsiderar la respuesta del usuario 1052645. Es más simple, no requiere conocimiento de los valores máximos y podría ser más rápido (suponiendo que evaluar una expresión puede ser más rápido que una llamada a función).
Steve Clay

Respuestas:

568

MySQL tiene una sintaxis no documentada para ordenar los nulos en último lugar. Coloque un signo menos (-) antes del nombre de la columna y cambie el ASC a DESC:

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

Es esencialmente lo position DESCcontrario de colocar los valores NULOS al final, pero por lo demás es lo mismo que position ASC.

Una buena referencia está aquí http://troels.arvin.dk/db/rdbms#select-order_by

Jarred
fuente
79
No está indocumentado, - col_namees una expresión ( 0 - col_name), que acepta la cláusula ORDER BY. Por supuesto, esto solo funciona para columnas numéricas.
Steve Clay
77
Buena esa. Funciona para datey timecolumnas también! (MySQL 5.5). Supongo (que soy lento para verificar) funciona para todas las columnas de tipo numérico (marca de tiempo, flotante ...).
Martin
66
@koral: es una expresión matemática simple (y útil) que invierte el orden, no se eliminará a menos que el lenguaje en sí cambie drásticamente.
Bell
11
Como sugieren los comentarios, ¿funciona para columnas numéricas, de fecha y hora? Pero, ¿qué hay de varchar? ¿Se puede aplicar también para varchar? Intenté aplicarlo a los campos varchar, pero el orden parece ser diferente de usar ASC o DESC.
Sumit Desai
9
¿Esto no impedirá el uso de un posible índice en el pedido por columna?
Tarsis
306

Encontré que esta es una buena solución en su mayor parte:

SELECT * FROM table ORDER BY ISNULL(field), field ASC;
d -_- b
fuente
66
Sin redefinir el orden por obras: SELECT * FROM table ORDER BY ISNULL(field) ASC;(MySQL 5.5)
Marçal Juan
55
Esta es una mejor solución.
Rok Kralj
44
La solución aceptada no funciona con TIMESTAMP en postgresql 9.3. Esta solución hace ...
Kalu
2
Molesto, MySQL no usará un índice en el campo cuando agrega isnull (campo) al orden por cláusula (cuando usa límite).
Barry Kelly
3
@kalu: en PostgreSQL , los valores NULL se ordenan en último lugar en orden ascendente (y primero en orden descendente). Y prefiere usar la cláusula SQL estándarNULLS LAST | NULLS FIRSTpara voltearlo en lugar de las soluciones alternativas aquí.
Erwin Brandstetter
23

Algo como

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

Reemplace 999999999 con el valor máximo para el campo

DrewM
fuente
3
Esta solución es frágil y puede provocar errores intermitentes
Dmitry Bogdanovich
20

NULO ÚLTIMO

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

Puede intercambiar instancias de NULL con un valor diferente para ordenarlas primero (como 0 o -1) o la última (un número grande o una letra) ...

SELECT field1, IF(field2 IS NULL, 9999, field2) as ordered_field2
  FROM tablename
 WHERE visible = 1
 ORDER BY ordered_field2 ASC, id DESC
Langdon
fuente
Esto no resolverá el problema ya que el índice al que se hace referencia en ORDER BY no se verá afectado al reemplazar los valores en la instrucción SELECT y, por lo tanto, no corregirá el orden. Además, consulte la función COALESCE, que es funcionalmente equivalente a su uso de la función IF.
define el
Si alias la instrucción IF correctamente, las filas se ordenan como es de esperar. Arreglé mi ejemplo.
Langdon el
4

Intenta usar esta consulta:

SELECT * FROM tablename
WHERE visible=1 
ORDER BY 
CASE WHEN position IS NULL THEN 1 ELSE 0 END ASC,id DESC
Rachit Patel
fuente
No es necesario para el caso. IS NULL devuelve 1 cuando la expresión es NULL. Ver la respuesta de reverbnation.
contactmatt
3

Puede fusionar sus NULL en la ORDER BYdeclaración:

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

Si desea que los NULL se ordenen en la parte inferior, intente coalesce(position, 100000). (Haga el segundo número más grande que todos los demás positionen la base de datos).

Seth
fuente
3
SELECT * FROM tablename WHERE visible=1 ORDER BY CASE WHEN `position` = 0 THEN 'a' END , position ASC
YasirPoongadan
fuente
66
¿Por qué el OP debería intentar esto ? Las buenas respuestas siempre tendrán una explicación de lo que se hizo y por qué se hizo de esa manera, no solo para el OP sino para los futuros visitantes a SO que pueden encontrar esta pregunta y leer su respuesta.
RiggsFolly
2

Para una DATEcolumna puede usar:


NULOS últimos:

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

Los últimos espacios en blanco:

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

Para lograr el siguiente resultado:

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

USE la sintaxis, coloque -(minus sign)antes del nombre del campo y use el tipo de orden inverso (como: si desea ordenar por orden ASC, use DESC o si desea orden DESC, use ASC)

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

Nishu Garg
fuente
1

Esto está funcionando bien:

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

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

¿Por qué no ordena por NULLS ULTIMO?

SELECT * 
FROM tablename
WHERE visible = 1 
ORDER BY position ASC NULLS LAST, id DESC 
Rover rojo
fuente
NULLS LAST- ¿Qué versión de MySQL se introdujo?
crmpicco
2
@Panique, ¿te refieres a (MS) SQL Server?
d -_- b
1
esta respuesta no se aplica a MySQL
PeppyHeppy