Por que é que quando temos um valor NULL em uma coluna e ordenamos pelo valor crescente, os NULLs são classificados primeiro?
select 1 as test
union all
select 2
union all
select NULL
union all
select 3
union all
select 4
order by test
resulta em
NULL
1
2
3
4
Eu continuo pensando que NULL significava "Indeterminante" ou possível "Desconhecido". Se isso for verdade, eles não classificariam por último, já que o valor pode ser maior que todos os outros valores? (Ou esta é uma opção de classificação em algum lugar?)
Estou no SQL Server 2008R2, mas suspeito que isso seja verdade em todos os SQL Servers e provavelmente em todos os RDBMSs.
NULL significa desconhecido. Nenhuma outra interpretação é válida.
Não há poderia ser . Não há valor potencial . Desconhecido é desconhecido é desconhecido.
Quanto ao motivo pelo qual aparece primeiro, e não por último, isso não é atendido pelos padrões SQL publicados e, infelizmente, fica a critério do fornecedor do RDBMS:
Você está correto que
NULL
pode significar 'Indeterminante' ou 'Desconhecido' ou 'Ainda não conhecido' ou 'Não se aplica'. Mas não há razão para colocar os Nulos em primeiro ou em último lugar. Se não soubermos os valores reais, então eles podem ser pequenos ou grandes.Eu acho que o padrão para determinar o comportamento desejado de Nulls durante a classificação é:
Infelizmente o SQL-Server ainda não adotou esta sintaxe. Se não estou errado PostgreSQL e Oracle tem.
Uma solução:
Outra solução que precisa de ajuste dependendo do tipo de dados - mas não funcionará bem, pois não pode usar um índice em
(test)
:Não sei por que é feito dessa maneira, mas, por definição, NULLS não pode ser comparado a não-NULLS, então eles precisam ir no início ou no final (a resposta de Mark cobre isso com muito mais detalhes).
Para obter o comportamento desejado - Até onde eu sei, não há opção de classificação para colocar os nulos por último, então você precisa usar uma coluna computada para forçá-los por último. No entanto, no SQL Server você não pode ordenar por uma coluna computada (
CASE WHEN ...
) quando seus dados contêm um operador de conjunto (UNION ALL
). Então:Funcionará para classificar os nulos por último. Se você precisar usar
UNION
(ouEXCEPT
ouINTERSECTS
) para gerar seu conjunto de dados, despeje seus dados em uma tabela temporária como acima.Se você está lidando com números, você também pode usar
NULL
são os valores mais baixos possíveis, portanto,DESC
os coloca no final. Enquanto isso, os valores não nulos têm o sinal invertido, portanto,DESC
na verdade, é umASC
valor real. Isso deve ser mais rápidoCASE
e suponho que o otimizador de consulta também possa usar índices natest
coluna.