W ANSI SQL standard określa (Rozdział 6.5, zestaw opis funkcji) następujące zachowanie zagregowanych funkcjami zbiór pusty Wynik:
COUNT(...) = 0
AVG(...) = NULL
MIN(...) = NULL
MAX(...) = NULL
SUM(...) = NULL
Zwracanie wartości NULL dla AVG, MIN i MAX ma idealny sens, ponieważ średnia, minimalna i maksymalna pustego zestawu jest niezdefiniowana.
Ten ostatni jednak denerwuje mnie: Matematycznie, suma zbioru pustego jest dobrze zdefiniowana: 0
. Używając 0, neutralny element dodawania, ponieważ podstawowy przypadek sprawia, że wszystko jest spójne:
SUM({}) = 0 = 0
SUM({5}) = 5 = 0 + 5
SUM({5, 3}) = 8 = 0 + 5 + 3
SUM({5, NULL}) = NULL = 0 + 5 + NULL
Zdefiniowanie SUM({})
jako null
zasadniczo sprawia, że „brak wierszy” jest specjalnym przypadkiem, który nie pasuje do innych:
SUM({}) = NULL = NULL
SUM({5}) = 5 != NULL + 5 (= NULL)
SUM({5, 3}) = 8 != NULL + 5 + 3 (= NULL)
Czy jest jakaś oczywista zaleta dokonanego wyboru (SUMA ma wartość NULL), którego przegapiłem?
Odpowiedzi:
Obawiam się, że powodem jest po prostu to, że reguły zostały ustalone w sposób doraźny (podobnie jak wiele innych „cech” standardu ISO SQL) w czasie, gdy agregacje SQL i ich związek z matematyką były mniej zrozumiałe niż są obecnie (*).
To tylko jedna z bardzo wielu niespójności w języku SQL. Sprawiają, że język jest trudniejszy do nauczenia, trudniejszy do nauczenia się, trudniejszy do zrozumienia, trudniejszy w użyciu, trudniejszy do wszystkiego, czego chcesz, ale tak po prostu jest. Z oczywistych powodów kompatybilności wstecznej nie można zmienić reguł „na zimno” i „tak po prostu” (jeśli komitet ISO opublikuje ostateczną wersję normy, a następnie dostawcy zaczną wdrażać tę normę, to ci dostawcy nie docenią bardzo, jeśli w kolejnej wersji reguły są zmieniane w taki sposób, że istniejące (zgodne) implementacje poprzedniej wersji standardu „automatycznie nie spełniają” nowej wersji ...)
(*) Teraz lepiej jest zrozumieć, że agregacje w pustym zbiorze zachowują się bardziej konsekwentnie, jeśli systematycznie zwracają wartość tożsamości (= to, co nazywacie „elementem neutralnym”) bazowego operatora binarnego. Podstawowym operatorem binarnym dla COUNT i SUM jest suma, a jego wartość identyfikacyjna wynosi zero. W przypadku MIN i MAX ta wartość tożsamości jest odpowiednio najwyższą i najniższą wartością danego typu, jeśli dane typy są skończone. Przypadki takie jak uśrednianie, środki harmoniczne, mediany itp. Są jednak niezwykle skomplikowane i egzotyczne pod tym względem.
źródło
HIGHEST()
wiele, nie jest elementem typu danych, jak w przypadku Reals, gdzie tożsamość byłaby-Infinity
(i+Infinity
dlaLOWEST()
)W sensie pragmatycznym
NULL
przydatny jest obecny wynik . Rozważ następującą tabelę i instrukcje:Pierwsza instrukcja zwraca NULL, a druga zwraca zero. Gdyby pusty zestaw zwrócił zero
SUM
, potrzebowalibyśmy innego sposobu na odróżnienie prawdziwej sumy zerowej od pustego zestawu, być może używając licznika. Jeśli rzeczywiście chcemy zerowego dla pustego zestawu, prostyCOALESCE
spełni to wymaganie.źródło
COALESCE()
ten sposób nie rozróżnia0
sumy ( ) pustego zestawu odNULL
sumy () (powiedzmy, że tabela miała(10, NULL)
wiersz.SUM
kolumnę i wrócę do zera, to wiem bez konieczności sprawdzania, że co najmniej jeden wiersz nie jest NULL używany do wyświetlenia wyniku.DECODE(count(c2),0,NULL,sum(c2))
kiedy jest.Główną różnicą, którą widzę, jest w odniesieniu do typu danych. COUNT ma dobrze określony typ powrotu: liczba całkowita. Wszystkie pozostałe zależą od typu kolumny / wyrażenia, na które patrzą. Ich typ zwrotu musi być zgodny ze wszystkimi elementami zestawu (think float, currency, decimal, bcd, timespan, ...). Ponieważ nie ma zestawu, nie można sugerować typu zwrotu, dlatego NULL jest najlepszą opcją.
Uwaga: w większości przypadków możesz sugerować typ zwracany z typu kolumny, na który patrzysz, ale możesz wykonywać SUMY nie tylko na kolumnach, ale na wszelkiego rodzaju rzeczach. Implikacja typu zwrotu może być bardzo trudna, jeśli nie niemożliwa, w pewnych okolicznościach, szczególnie gdy myślisz o możliwych rozszerzeniach standardu (przychodzą na myśl typy dynamiczne).
źródło
SUM(column)
wyrażeniu? Czy nie mamy pustych tabel - a tam wszystkie kolumny mają zdefiniowane typy? Dlaczego miałoby być inaczej w przypadku pustego zestawu wyników?24 + 56.07 + '2012-10-05' + 'Red'
? Mam na myśli, że nie ma wątpliwości, jakSUM()
się zachowamy, gdy będziemy mieli problem ze zdefiniowaniem dodatku.