ANSI SQL이 SUM (no rows)을 NULL로 정의하는 이유는 무엇입니까?


28

ANSI SQL 표준을 정의 (제 6.5 장, 설정 기능 사양) 빈 결과 집합에 집계 함수에 대한 다음과 같은 동작 :

COUNT(...) = 0
AVG(...) = NULL
MIN(...) = NULL
MAX(...) = NULL
SUM(...) = NULL

빈 세트의 평균, 최소 및 최대 값이 정의되어 있지 않으므로 AVG, MIN 및 MAX에 NULL을 반환하는 것이 완벽합니다.

그러나 마지막 것은 나를 귀찮게합니다 : 수학적으로 빈 세트의 SUM은 잘 정의되어 있습니다 : 0. 기본 사례가 모든 것을 일관성있게하기 때문에 추가 의 중립 요소 인 0을 사용합니다 .

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)의 명백한 이점이 있습니까?


참고 : 이것은 SQL Server에 대해 StackOverflow에 대해 질문 한 일반화 된 버전입니다 .
Heinzi

5
예, 동의합니다 : COUNT 및 SUM이 일관되게 동작하지 않습니다.
AK

답변:


20

이유 는 SQL 집계와 수학과의 연관성이 현재보다 이해가 잘되지 않는시기에 규칙이 임시 방식 ( ISO SQL 표준 의 다른 많은 "기능"과 같이 )으로 설정 되었기 때문입니다. (*).

SQL 언어에서 매우 많은 불일치 중 하나 일뿐입니다. 그것들은 언어를 가르치기 어렵고 배우기 어렵고 이해하기 어렵고 사용하기 어렵고 원하는 것을 어렵게 만듭니다. 그러나 그것은 바로 상황입니다. 하위 호환성의 명백한 이유로 규칙을 "감기"및 "그런 식으로"변경할 수 없습니다 (ISO위원회에서 표준의 최종 버전을 게시 한 후 공급 업체가 해당 표준을 구현하기로 결정한 경우 해당 공급 업체는 감사하지 않습니다. 후속 버전에서 표준의 이전 버전에 대한 기존 (호환되는) 구현이 새 버전을 "자동으로 준수하지 못하도록"규칙이 변경되면 ...)

(*) 빈 집합에 대한 집계 는 기본 이진 연산자 의 ID 값 (= '중립 요소'라고 함)을 체계적으로 반환하면 더 일관되게 동작한다는 것이 더 잘 이해됩니다 . COUNT 및 SUM에 대한 기본 이진 연산자는 더하기이며 해당 ID 값은 0입니다. MIN 및 MAX의 경우 관련 유형이 유한 한 경우 해당 항등 값은 각각 해당 유형의 최고 및 최저 값입니다. 그러나 평균화, 고조파 수단, 중간 값 등과 같은 사례는이 점에서 매우 복잡하고 이국적입니다.


null과 min 및 max가있는 빈 세트에 의미가 있다고 생각합니다. 실제로 식별 값을 알 수는 없지만 n * 0이 항상 0 인 것과 같은 이유로 값의 합은 0입니다. 그러나 min과 max는 다릅니다. 나는 레코드가없는 상태에서 결과가 올바르게 정의되어 있다고 생각하지 않습니다.
Chris Travers

또한이 컨텍스트에서 0/0이 올바르게 정의되지 않았기 때문에 널 세트에 대한 avg ()는 널로 의미가 있습니다.
Chris Travers

5
MIN과 MAX는 크게 다르지 않습니다. 기본 이진 연산자 LOWESTOF (x, y) 및 HIGHESTOF (x, y)를 각각 취하십시오. 이 이항 연산자에는 항등 값이 있습니다. 두 경우 모두 (포함 된 유형이 유한 한 경우) forall x : LOWESTOF (z, x) = x 및 forall y : HIGHESTOF (y, z) = y와 같은 z 값이 실제로 존재하기 때문입니다. (동일한 값은 두 경우 모두 동일하지 않지만 두 경우 모두 존재합니다.) 결과가 언뜻보기에 매우 직관적으로 보이지만 수학적 현실을 부정하지는 않는다는 데 동의합니다.
Erwin Smout

@Erwin : 나는 모든 점에 동의, 같은 일부 작업의 신원 것을 제외하고 HIGHEST()레알의 ID가 될 곳처럼 많은 사람들이, 데이터 유형의 요소가 될 수 없습니다 -Infinity(그리고 +Infinity를 위해 LOWEST())
ypercubeᵀᴹ

1
@SQL 키위. 정적 유형 검사를 잊고 있습니까? SUM ()과 같은 표현식이 정적 유형 검사기에서 항상 정수를 리턴하는 것처럼 처리되는 경우 SUM () 호출이 때때로 정수 가 아닌 것을 리턴하는 것은 불가능 합니다 (예 : 빈 관계).
Erwin Smout

3

실용적인 의미에서 기존 결과 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을 반환하고 두 번째 문은 0을 반환합니다. 빈 세트가 0을 반환 SUM하면 실제 개수와 0을 빈 세트와 구별하는 다른 방법이 필요할 수 있습니다. 빈 세트에 실제로 0을 원하면 간단한 COALESCE요구 사항을 제공합니다.

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

1
결과적으로, SUM (set1과 set2의 연합) <> SUM (set1) + SUM (set2)는 숫자 + NULL = NULL이므로 SUM (set1) + SUM (set2)입니다. 당신에게 이치에 맞습니까?
AK

2
@Leigh : 이렇게 사용 하면 빈 집합 COALESCE()의 ( 0) 합계와 ( ) 합계가 구분되지 않습니다 NULL(예 : 테이블에 (10, NULL)행이 있음)
ypercubeᵀᴹ at

게다가, 우리는 여전히 SUM (빈 세트)을 SUM (하나 이상의 NULL 세트)과 구별 할 수 없습니다. 우리는 전혀 구별해야합니까?
AK

@AlexKuznetsov-하나 이상의 행에 값이 포함되어 있으면 빈 집합의 합을 하나 이상의 널을 포함하는 집합의 합과 구별 할 수 있습니다. 집합에 NULL 만 포함 된 경우 NULL 집합을이 모든 NULL 값 집합과 구분할 수없는 것이 맞습니다. 내 요점은 모든 경우에 유용하다는 것이 아니라 유용 할 수 있다는 것입니다. 내가하면 SUM열 및이 적어도 하나하지 NULL 행입니다 나에게 결과를 표시하는 데 사용하고 있는지 확인하지 않고 다시 내가 아는 제로를 얻을.
레이 리펠

@ypercude-당신은 절대적으로 정확합니다. 내 요점은 SUM의 현재 동작이 빈 세트를 값이 포함 된 세트와 구별한다는 것입니다 (일부는 null 인 경우에도). 구별이 필요하지 않을 DECODE(count(c2),0,NULL,sum(c2))때 와 같이 무언가를 사용하는 것보다 COALESCE를 사용하는 것이 더 간단합니다 .
레이 리펠

-1

내가 볼 수있는 주요 차이점은 데이터 유형과 관련이 있습니다. COUNT에는 잘 정의 된 반환 유형이 있습니다. 정수 다른 모든 항목은보고있는 열 / 표현 유형에 따라 다릅니다. 반환 유형은 세트의 모든 멤버와 호환 가능해야합니다 (float, currency, decimal, bcd, timespan, ...). 집합이 없으므로 반환 유형을 암시 할 수 없으므로 NULL이 가장 좋습니다.

참고 : 대부분의 경우보고있는 열 형식에서 반환 형식을 암시 할 수 있지만 열뿐만 아니라 모든 종류의 작업에서 SUM을 수행 할 수 있습니다. 특정 상황에서, 특히 표준의 확장 가능성에 대해 생각할 때 (동적 유형이 떠오를 때) 리턴 유형을 암시하는 것은 매우 어려울 수 있습니다.


5
SUM(column)표현식 에서 리턴 유형을 암시 할 수없는 이유는 무엇 입니까? 빈 테이블이없고 모든 열에 정의 된 유형이 있습니까? 빈 결과 집합이 다른 이유는 무엇입니까?
ypercubeᵀᴹ

5
" NO SET 가 없기 때문에"라고 말하면 잘못 됩니다. 세트가 있습니다. 관련된 열 또는 표현식의 선언 된 유형에 가능한 모든 값 세트. 보고있는 테이블이 비어 있어도 선언 된 형식이 존재합니다. 빈 테이블조차도 여전히 제목이 있습니다. 그리고 선언 된 타입은 정확히 "암시적인 리턴 타입"입니다.
Erwin Smout

둘 다 실제로 내 쪽지를 읽었습니까? 예, 현재 열 기반 SUM에서 작동합니다. 그러나 변수 datatype-column (SQL Server가 아닌)이 발생하면 운이 좋지 않습니다.
TToni

2
이 경우 합계를 어떻게 정의합니까? 결과는 24 + 56.07 + '2012-10-05' + 'Red'어떻습니까? SUM()덧셈을 정의하는데 문제가있을 때 어떻게 행동 할 것인지 걱정할 필요가 없습니다 .
ypercubeᵀᴹ

1
@TToni : "특히 표준의 확장 가능성에 대해 생각할 때"는 OP가 언급 한 맥락이 아닙니다. OP는 현재 버전의 표준을 명확하게 언급하고 있는데, 여기에는 "동적 유형"이나 그와 같은 개념이 포함되지 않습니다. (아, 그리고 나는 단지 의견을 말했지만, 공감하지 않았다. 내가 문제를
겪은
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.