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.