No script a seguir ( veja uma demonstração completa aqui ):
SELECT *
FROM Table1
ORDER BY
CASE WHEN Field1 IS NOT NULL
THEN 0
END
- Qual é o tipo do
0
? - Como
0
é interpretado? Não é o número ordinal das colunas na lista de seleção, porque a enumeração da lista de seleção começa com 1, não com 0. Então, o que é?
Para elaborar um pouco, compare o trecho acima com o seguinte, que emite um erro:
SELECT *
FROM Table1
ORDER BY 0
A posição ORDER BY número 0 está fora do intervalo do número de itens na lista de seleção.
E também compare com o seguinte snippet, que emite outro erro:
SELECT *
FROM Table1
ORDER BY '0'
Uma expressão constante foi encontrada na lista ORDER BY, posição 1.
Parece que aninhar o 0
valor em uma case
cláusula faz com que funcione, mas não entendo por que e como?
- Esta pergunta é um pouco uma continuação desta antiga, que não explica porque funciona em comparação com as alternativas que listei acima: Como funciona o SQL com ordem por 0?
A documentação da cláusula ORDER BY afirma:
O doc poderia, sem dúvida, afirmar isso mais claramente. De acordo com a segunda frase, "coluna" pode ser especificada como:
CASE
é uma "expressão" em vez de uma especificação de coluna. A expressão não especifica uma coluna de ordem de classificação. O valor da expressão result é usado para classificação.O resultado da expressão
CASE WHEN Field1 IS NOT NULL THEN 0 END
é um inteiro (devido à constante de inteiro zero) com valor zero ouNULL
. As informações do tipo de expressão podem ser obtidas comsys.dm_exec_describe_first_result_set
:Usando dados ligeiramente modificados de seu violino e uma expressão CASE válida, você pode ver que as linhas com valores NULL são classificadas antes daquelas com valores não nulos porque a expressão CASE retornou um NULL para linhas com um valor NULL Field1 e um zero para linhas com valores não NULL.
Acrescentarei que, como NULLs classificam antes de valores não NULL, pode-se simplesmente ordenar por Field1 para fornecer o comportamento de classificação desejado e talvez alavancar um índice na coluna também. Ao contrário da expressão CASE, este método também classificará valores não NULL de acordo com o valor Field1 em vez da ordem indefinida dos valores zero da expressão CASE (devido aos laços de valores zero).
Quando você usa uma expressão (por exemplo
CASE
, ), ela não está mais classificando por nome de coluna ou pelo ordinal da coluna, mas agora por valor . Esse valor que você escolheu é 0 neste caso (apenas paraField1
linhas não nulas), mas poderia ter sido 1, 100, 'Red' ou atéFieldSomethingElse
.Se você construísse sua
CASE
expressão um pouco mais, você veria o que quero dizer:O acima classifica as linhas semi-descendentes com base se o valor de
Field1
for maior que um determinado valor. Ele também tem um caso padrão, aELSE
cláusula, que colocará todas as linhas ondeField1 IS NULL
no final dos resultados.Obviamente, não há colunas com um nome ou com um ordinal de 100, 200, 300 ou 900, mas a
CASE
expressão acima funciona porque o SQL Server classifica as linhas pelos valores naTHEN
cláusula para as linhas que atendem a essaWHEN
cláusula.A mesma coisa está acontecendo em sua
CASE
cláusula de exemplo quando você usa 0, está apenas classificando linhas não nulas no valor constante 0. Isso obviamente não significa muito em termos de classificação, exceto que todas as linhas não nulas serão classificadas juntos (já que todos serão classificados no mesmo valor de 0 e, portanto, sua ordem nessa classificação será não determinística) e todas as linhas nulas também serão classificadas juntas.A instrução de pedido gera um 'campo virtual' que contém NULL ou 0 com base na condição do caso.
O ORDER BY é aplicado com base nesse campo virtual.
O valor zero na ordem por precede o valor NULL. Isso é tudo, é uma maneira de definir NULLs do campo1 no final da lista de pedidos.
Tente visualizá-lo desta forma: