El estándar ANSI SQL define (capítulo 6.5, especificación de la función de conjunto) el siguiente comportamiento para funciones agregadas en conjuntos de resultados vacíos:
COUNT(...) = 0
AVG(...) = NULL
MIN(...) = NULL
MAX(...) = NULL
SUM(...) = NULL
Devolver NULL para AVG, MIN y MAX tiene mucho sentido, ya que el promedio, mínimo y máximo de un conjunto vacío no está definido.
El último, sin embargo, que me molesta: Matemáticamente, la suma de un conjunto vacío está bien definido: 0
. Usando 0, el elemento neutral de suma, como el caso base hace que todo sea consistente
SUM({}) = 0 = 0
SUM({5}) = 5 = 0 + 5
SUM({5, 3}) = 8 = 0 + 5 + 3
SUM({5, NULL}) = NULL = 0 + 5 + NULL
Definir SUM({})
como null
básicamente hace que "sin filas" sea un caso especial que no encaja con los demás:
SUM({}) = NULL = NULL
SUM({5}) = 5 != NULL + 5 (= NULL)
SUM({5, 3}) = 8 != NULL + 5 + 3 (= NULL)
¿Hay alguna ventaja obvia de la elección que se hizo (SUM siendo NULL) que me he perdido?
Respuestas:
Me temo que la razón es simplemente que las reglas se establecieron de manera ad hoc (como muchas otras "características" del estándar ISO SQL) en un momento en que las agregaciones SQL y su conexión con las matemáticas eran menos entendidas de lo que son ahora. (*)
Es solo una de las muchas inconsistencias en el lenguaje SQL. Hacen que el idioma sea más difícil de enseñar, más difícil de aprender, más difícil de entender, más difícil de usar, más difícil de lo que quieras, pero así son las cosas. Las reglas no se pueden cambiar "en frío" y "así", por razones obvias de compatibilidad con versiones anteriores (si el comité ISO publica una versión final del estándar, y los proveedores se proponen implementar ese estándar, entonces esos proveedores no lo apreciarán mucho si en una versión posterior, las reglas se cambian de tal manera que las implementaciones existentes (compatibles) de la versión anterior del estándar "no cumplan automáticamente" la nueva versión ...)
(*) Ahora se entiende mejor que las agregaciones sobre un conjunto vacío se comportan de manera más consistente si devuelven sistemáticamente el valor de identidad (= lo que llama el 'elemento neutral') del operador binario subyacente en cuestión. Ese operador binario subyacente para COUNT y SUM es la suma, y su valor de identidad es cero. Para MIN y MAX, ese valor de identidad es el valor más alto y más bajo del tipo en cuestión, respectivamente, si los tipos en cuestión son finitos. Sin embargo, casos como el promedio, los medios armónicos, las medianas, etc. son extremadamente intrincados y exóticos a este respecto.
fuente
HIGHEST()
muchas, no será un elemento del tipo de datos, como para Reals, donde la identidad sería-Infinity
(y+Infinity
paraLOWEST()
)En un sentido pragmático, el resultado existente de
NULL
es útil. Considere la siguiente tabla y declaraciones:La primera instrucción devuelve NULL y la segunda devuelve cero. Si un conjunto vacío devuelve cero
SUM
, necesitaríamos otro medio para distinguir una suma verdadera de cero de un conjunto vacío, tal vez usando count. Si realmente queremos cero para el conjunto vacío, entonces un simpleCOALESCE
proporcionará ese requisito.fuente
COALESCE()
de este tipo no distinguirá la (0
suma) de un conjunto vacío de la (NULL
suma) (decir la mesa que había una(10, NULL)
fila.SUM
una columna y vuelvo a cero, lo sé sin tener que verificar que haya al menos una fila que no sea NULL para mostrarme el resultado.DECODE(count(c2),0,NULL,sum(c2))
cuando lo es.La principal diferencia que puedo ver es con respecto al tipo de datos. COUNT tiene un tipo de retorno bien definido: un número entero. Todos los demás dependen del tipo de columna / expresión que están viendo. Su tipo de retorno debe ser compatible con todos los miembros del conjunto (piense en flotante, moneda, decimal, bcd, intervalo de tiempo, ...). Como no hay un conjunto, no puede implicar un tipo de retorno, por lo tanto, NULL es su mejor opción.
Nota: En la mayoría de los casos, podría implicar un tipo de retorno del tipo de columna que está viendo, pero puede hacer SUMAS no solo en columnas sino en todo tipo de cosas. Implicar un tipo de retorno puede ser muy difícil, si no imposible, bajo ciertas circunstancias, especialmente cuando se piensa en posibles expansiones del estándar (los tipos dinámicos vienen a la mente).
fuente
SUM(column)
expresión? ¿No tenemos tablas vacías y todas las columnas tienen tipos definidos? ¿Por qué debería ser diferente para un conjunto de resultados vacío?24 + 56.07 + '2012-10-05' + 'Red'
ser? Quiero decir que no hay problema en preocuparse por cómoSUM()
se comportará cuando tengamos un problema para definir la suma.