¿Por qué se ordenan los NULL primero?


20

¿Por qué es que cuando tenemos un valor NULL en una columna y ordenamos por el valor ascendente, los NULL se ordenan primero?

select 1 as test
union all
select 2
union all
select NULL
union all
select 3
union all
select 4
order by test

resultados en

NULL
1
2
3
4

Sigo pensando que NULL significa "Indeterminante" o posible "Desconocido". Si eso es cierto, ¿no lo ordenarían al final, ya que el valor podría ser mayor que todos los demás valores? (¿O es esta una opción de clasificación en alguna parte?)

Estoy en SQL Server 2008R2, pero sospecho que esto es cierto en todos los servidores SQL, y probablemente en todos los RDBMS.


1
Oracle lo enumera al final. Eso me fastidió una vez, creyendo que debería comportarse como SQL Server.
Andrei Rînea

2
"Si eso es cierto, no lo ordenarían al final, ya que el valor podría ser mayor que todos los demás valores". El valor podría ser menor que todos los demás valores también. Para mí, es intuitivo que un valor falso como nulo debería estar en el extremo inferior. Y práctico, ya que en la práctica, a menudo quieres usar el descorden para mostrar las cosas más grandes o más recientes, en cuyo caso me alegraría que las cosas nulas sean las últimas.
mahemoff

La base de datos hace lo que le dices que haga. Si sabe que sus datos contienen valores nulos y tiene alguna razón comercial para ordenar los datos de cierta manera, entonces debe especificar eso en la consulta o en el código / vista que procesa / muestra los datos. Nunca deje la clasificación al comportamiento predeterminado de la base de datos.
nada es necesario

Respuestas:


19

BOL : un valor de NULL indica que el valor es desconocido. Un valor de NULL es diferente de un valor vacío o cero. No hay dos valores nulos iguales. Las comparaciones entre dos valores nulos, o entre un NULL y cualquier otro valor, devuelven desconocido porque el valor de cada NULL es desconocido.

NULL significa desconocido. Ninguna otra interpretación es válida.

Si eso es cierto, ¿no lo ordenarían al final, ya que el valor podría ser mayor que todos los demás valores?

No hay podría ser . No hay valor potencial . Desconocido es desconocido es desconocido.

En cuanto a por qué aparece primero, en lugar de al final, esto no es atendido por los estándares SQL publicados y desafortunadamente se deja a discreción del proveedor de RDBMS:

Wikipedia : El estándar SQL no define explícitamente un orden de clasificación predeterminado para Nulls. En cambio, en sistemas conformes, los valores nulos se pueden ordenar antes o después de todos los valores de datos utilizando las cláusulas NULLS FIRST o NULLS LAST de la lista ORDER BY, respectivamente. Sin embargo, no todos los proveedores de DBMS implementan esta funcionalidad. Los proveedores que no implementan esta funcionalidad pueden especificar diferentes tratamientos para la ordenación nula en el DBMS.


Entonces, es una decisión judicial. Eso tiene mucho sentido. ¡Gracias!
Richard

6

Está en lo correcto, lo que NULLpuede significar 'Indeterminante' o 'Desconocido' o 'Aún no se conoce' o 'No se aplica'. Pero no hay razón para poner a los nulos primero o último. Si no conocemos los valores reales, entonces tehy puede ser pequeño o grande.

Creo que el estándar para determinar el comportamiento deseado de Nulls durante la ordenación es:

ORDER BY 
    test NULLS LAST                      --- or NULLS FIRST for the opposite

Lamentablemente, SQL-Server aún no ha adoptado esta sintaxis. Si no me equivoco, PostgreSQL y Oracle lo tienen.

Una solución:

ORDER BY 
     CASE WHEN test IS NOT NULL 
            THEN 0 
          ELSE 1 
     END 
   , test

Otra solución que necesita un ajuste según el tipo de datos, pero no se formará bien, ya que no puede usar un índice en (test):

ORDER BY 
    COALESCE(test, 2147483647)               --- if it's a 4-byte signed integer

De esta manera, ORDER BY COALESCE (prueba, 2147483647) el servidor SQL no puede usar Index.
Ardalan Shahgholi

3

No sé por qué se hace de esa manera, pero, por definición, los NULLS no se pueden comparar con los que no son NULLS, por lo que deben ir al principio o al final (la respuesta de Mark cubre esto con mucho más detalle).

Para obtener el comportamiento que desea: Hasta donde yo sé, no hay una opción de clasificación para poner los nulos en último lugar, por lo que debe modificarlo utilizando una columna calculada para forzarlos al último. Sin embargo, en SQL Server no puede ordenar por una columna calculada ( CASE WHEN ...) cuando sus datos contienen un operador establecido ( UNION ALL). Entonces:

CREATE TABLE #sorttest(test int)
INSERT INTO #sorttest values(1)
INSERT INTO #sorttest values(5)
INSERT INTO #sorttest values(4)
INSERT INTO #sorttest values(NULL)
INSERT INTO #sorttest values(3)
INSERT INTO #sorttest values(2)
SELECT test
FROM #sorttest
ORDER BY CASE WHEN test IS NULL THEN 1 ELSE 0 END, test

DROP TABLE #sorttest

Funcionará para ordenar los nulos al final. Si usted tiene que utilizar UNION(o EXCEPTo INTERSECTS) para generar el conjunto de datos, y luego volcar los datos a una tabla temporal que el anterior.


... o use la salida UNIONed como una tabla derivada.
Andriy M

0

Si se trata de números, también puede usar

ORDER BY -test DESC

NULLson los valores más bajos posibles, por DESClo tanto los pone al final. Mientras tanto, los valores no nulos tienen el signo invertido, por lo que en DESCrealidad es un ASCvalor real. Esto debería ser más rápido CASEy supongo que el optimizador de consultas también puede usar índices en la testcolumna.


3
No, no podría usar un índice para el tipo. A menos que tenga un índice en la expresión calculada (- test).
ypercubeᵀᴹ

1
Inteligente, aunque limitado a datos numéricos solamente (apropiado para el ejemplo de OP de todos modos). No estoy seguro de si esto sería más rápido que usar CASE, pero estoy seguro de que no usaría un índice (a menos que sea lo que dice @ ypercubeᵀᴹ, pero luego una expresión CASE podría indexarse ​​exactamente de la misma manera).
Andriy M
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.