MySQL Orderpor um número, os nulos duram


279

Atualmente, estou fazendo um OrderBy muito básico na minha declaração.

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

O problema é que as entradas NULL para 'position' são tratadas como 0. Portanto, todas as entradas com posição como NULL aparecem antes daquelas com 1,2,3,4. por exemplo:

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

Existe uma maneira de obter o seguinte pedido:

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

8
Você deve reconsiderar a resposta do usuário1052645. É mais simples, não requer conhecimento de valores máximos e pode ser mais rápido (assumindo que avaliar uma expressão possa ser mais rápido que uma chamada de função).
Steve argila

Respostas:


566

O MySQL possui uma sintaxe não documentada para classificar os nulos por último. Coloque um sinal de menos (-) antes do nome da coluna e mude o ASC para DESC:

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

É essencialmente o inverso de position DESCcolocar os valores NULL por último, mas o mesmo que position ASC.

Uma boa referência está aqui http://troels.arvin.dk/db/rdbms#select-order_by


79
Não está documentado, - col_nameé uma expressão ( 0 - col_name) que a cláusula ORDER BY aceita. Claro que isso só funciona para colunas numéricas.
Steve argila

7
Agradável. Funciona para datee timecolunas também! (MySQL 5.5). Eu acho que (tenho preguiça de verificar) funciona para todas as colunas semelhantes a números (carimbo de data / hora, flutuação ...).
Martin

6
@koral: é uma expressão matemática simples (e útil) que reverte a ordem e não será removida, a menos que a própria linguagem mude drasticamente.
Sino

11
Como os comentários sugerem, ele funciona para colunas numéricas, de data e hora? Mas e o varchar? Também pode ser aplicado ao varchar? Eu tentei aplicá-lo aos campos varchar, mas a ordem parece ser diferente do que usar ASC ou DESC.
Sumit Desai

9
Isso não impedirá o uso de um possível índice no pedido por coluna?
Tarsis

305

Eu achei que essa era uma boa solução para a maior parte:

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

6
Sem redefinir a ordem dos trabalhos: SELECT * FROM table ORDER BY ISNULL(field) ASC;(MySQL 5.5)
Marçal Juan

5
Esta é uma solução melhor.
Rok Kralj

4
A solução aceita não funciona com o TIMESTAMP no postgresql 9.3. Esta solução faz ...
kalu

2
Irritantemente, o MySQL não usará um índice no campo quando você adicionar isnull (field) à cláusula order by (ao usar limit).
Barry Kelly #

3
@kalu: No PostgreSQL , os valores NULL são classificados por último em ordem crescente (e primeiro em ordem decrescente). E você prefere usar a cláusula SQL padrãoNULLS LAST | NULLS FIRSTpara invertê-lo em vez das soluções alternativas aqui.
Erwin Brandstetter

23

Algo como

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

Substitua 999999999 por qualquer que seja o valor máximo do campo


3
Esta solução é frágil e pode levar a erros intermitentes
Dmitry Bogdanovich

20

NULL ÚLTIMO

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

4

Você pode trocar instâncias de NULL por um valor diferente para classificá-las primeiro (como 0 ou -1) ou por último (um número grande ou uma letra) ...

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

Isso não resolverá o problema, pois o índice mencionado em ORDER BY não será afetado pela substituição de valores na instrução SELECT e, portanto, não corrigirá a ordem. Além disso, verifique a função COALESCE, que é funcionalmente equivalente ao seu uso da função SE.
define

Se você alias a instrução SE corretamente, as linhas serão ordenadas conforme o esperado. Eu consertei meu exemplo.
Langdon

4

Tente usar esta consulta:

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

Não há necessidade de caso. IS NULL retorna 1 quando a expressão é NULL. Veja a resposta do reverbnation.
contactmatt

3

Você pode unir seus NULLs na ORDER BYinstrução:

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

Se você deseja que os NULLs sejam classificados na parte inferior, tente coalesce(position, 100000). (Faça o segundo número maior que todos os outros positionno banco de dados.)


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

6
Por que o OP deveria tentar isso ? Boas respostas sempre terão uma explicação do que foi feito e por que foi feito dessa maneira, não apenas para o OP, mas também para futuros visitantes do SO que possam encontrar essa pergunta e estar lendo sua resposta.
precisa saber é o seguinte

2

Para uma DATEcoluna, você pode usar:


Nulos por último:

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

Espaços em branco por último:

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

1

Para alcançar o seguinte resultado:

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

USE sintaxe, coloque -(minus sign)antes do nome do campo e use inverso order_type (como: se você deseja solicitar por ordem ASC, use DESC ou, se desejar, ordem DESC, use ASC)

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


1

Isso está funcionando bem:

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

position
1 
2
3
0
0

-8

Por que você não pede por NULLS ÚLTIMO?

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

NULLS LAST- qual versão do MySQL foi introduzida?
Crmpicco 15/05

2
@ Panique, você quer dizer (MS) SQL Server?
precisa

1
esta resposta não se aplica ao MySQL
PeppyHeppy
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.