web-dev-qa-db-ja.com

ANSI SQLがSUM(行なし)をNULLとして定義するのはなぜですか?

ANSI SQL標準で定義 (6.5章、関数の設定の仕様)空の結果セットでの集計関数の次の動作:

_COUNT(...) = 0
AVG(...) = NULL
MIN(...) = NULL
MAX(...) = NULL
SUM(...) = NULL
_

空のセットの平均値、最小値、最大値は定義されていないため、AVG、MIN、MAXにNULLを返すことは完全に理にかなっています。

ただし、最後の1つは私を悩ませます。数学的には、空のセットのSUMは明確に定義されています:_0_。基本ケースがすべてを一貫させるので、0を使用して、追加の neutral element を使用します。

_SUM({})        = 0    = 0
SUM({5})       = 5    = 0 + 5
SUM({5, 3})    = 8    = 0 + 5 + 3
SUM({5, NULL}) = NULL = 0 + 5 + NULL
_

SUM({})nullとして定義すると、基本的に「行なし」が他のケースに適合しない特別なケースになります。

_SUM({})     = NULL  = NULL
SUM({5})    = 5    != NULL + 5 (= NULL)
SUM({5, 3}) = 8    != NULL + 5 + 3 (= NULL)
_

私が見逃した選択(SUMがNULL)の明らかな利点はありますか?

28
Heinzi

理由は、ルールがアドホック方式で設定されたものであると恐れています(の他の多くの「機能」のように) [〜#〜] iso [〜#〜] SQL標準)SQL集計とその数学との接続が現在よりも理解されていなかったとき(*)。

これは、SQL言語における非常に多くの不整合の1つにすぎません。それらは言語を教えること、学習すること、理解すること、より使いにくく、あなたが望むものに対してより難しくしますが、それは物事のあり方です。下位互換性の明らかな理由により、ルールを「コールド」および「そのように」変更することはできません(ISO委員会が規格の最終バージョンを公開し、ベンダーがその規格の実装に着手した場合、それらのベンダーは感謝しません。後続のバージョンで、以前のバージョンの標準の既存の(準拠)実装が新しいバージョンを「自動的に準拠しない」ようにルールが変更された場合...)

(*)空のセットの集計は、基になるバイナリ演算子の識別値(=「中立要素」と呼ばれるもの)を体系的に返す場合、より一貫して動作することをよりよく理解できるようになりました。 COUNTおよびSUMの基礎となる2項演算子は加算であり、そのID値はゼロです。 MINおよびMAXの場合、関係する型が有限である場合、そのID値は、手元の型の最高値および最低値です。ただし、平均化、調和平均、中央値などのケースは、この点で非常に複雑でエキゾチックです。

20
Erwin Smout

実用的な意味で、NULLの既存の結果は役に立ちます。次の表とステートメントを検討してください。

C1 C2
-- --
 1  3 
 2 -1 
 3 -2 

SELECT SUM(C2) FROM T1 WHERE C1 > 9;

SELECT SUM(C2) FROM T1 WHERE C1 < 9;

最初のステートメントはNULLを返し、2番目のステートメントはゼロを返します。空のセットがSUMに対してゼロを返した場合、おそらくcountを使用して、ゼロの真の合計を空のセットと区別する別の手段が必要になります。実際に空のセットにゼロが必要な場合は、単純なCOALESCEでその要件が満たされます。

SELECT COALESCE(SUM(C2),0) FROM T1 WHERE C1 > 9;
3
Leigh Riffel