1. Null 값의 연산은 언제나 Null이다
- Null 값은 `공백이나 숫자 0`과는 전혀 다른 의미
- `아직 정의되지 않은 미지의 값` 또는 `현재 데이터를 입력하지 못하는 경우`를 의미
- 즉 Null은 값이 존재하지 않음을 말함
주문번호 | 주문금액 | 주문취소금액 |
1100001 | 100,000 | 20,000 |
1100002 | 15,000 |
위 주문 모델에 들어 있는 데이터를 바탕으로 SQL을 실행하면 다음과 같은 결과를 얻습니다.
- COL1, COL2, COL3는 최종 주문금액을 구하는 산식
- 최종 주문금액은 각 주문의 주문금액에서 취소된 주문금액을 제외한 결과
- [표 I-2-8] 결과를 보면 Null 값이 포함되었을 경우 COL1, COL2, 그리고 COL3의 결과가 모두 다르게 출력하는 것을 알 수 있는데 이는 Null 연산은 언제나 Null을 결과로 반환하기 때문
- Null 값으로 가능한 연산은 `IS NULL`과 `IS NOT NULL` 밖에 없음
COL1 | COL2 | COL3 |
80,000 | 80,000 | 80,000 |
0 | 15,000 |
부연 설명
- COL1은 최종주문금액을 구하기 위해 Null 값을 전혀 고려하지 않고, 주문금액에서 주문취소금액을 제외한 방식이므로 Null 값이 존재하지 않는 첫 번째 행의 결과는 정상적으로 80,000이 나오지만 Null 값이 존재하는 두 번째 행의 결과는 `15,000 - Null = Null`이라는 Null 값을 반환
- COL2는 주문금액에서 주문취소금액을 제외한 결과에 대해 NVL 처리를 하였으므로 Null 값이 존재하지 않는 첫 번째 행의 결과는 정상적으로 80,000이 나오지만 두 번째 결과는 `15,000 - Null = Null`로 Null 값을 반환하고 이때 NVL 함수로 인하여 Null 값을 0으로 변환하여 반환함
- COL3은 각 속성별로 NVL 처리를 하고, 이후 주문금액에서 주문취소금액을 제외하였기 때문에 Null 값에 대한 이해를 숙지한 경우로 볼 수 있음
- 속성별로 Null일 경우 NVL 함수를 사용하여 0으로 변환 후 연산을 처리하였기 때문에 두 번째 행에서 의도한 15,000이라는 결과가 나오게 됨
2. 집계함수는 Null 값을 제외하고 처리한다
아래 주문 모델의 주문취소금액은 전부 Null 값으로 아직 취소된 주문이 없는 상태이며 해당 데이터를 바탕으로 SQL을 실행하면 다음과 같은 결과를 얻습니다.
- COL1, COL2, 그리고 COL3은 최종주문금액 총합을 구하는 산식
- 최종주문금액은 각 주문의 주문금액에서 취소된 주문금액을 제외하고, 총합은 이를 합산한 결과
- 앞서 배웠듯 Null 값의 연산은 언제나 Null이기 때문에 집계함수는 Null 값의 경우는 제외하고 연산
- SUM 함수는 정의된 칼럼의 값을 모두 합산하는 함수로써 Null 값이 들어올 경우 이를 제외하고 처리
주문번호 | 주문금액 | 주문취소금액 |
1100001 | 100,000 | |
1100002 | 15,000 | |
1100003 | 40,000 | |
1100004 | 45,000 | |
1100005 | 100,000 |
COL1 | COL2 | COL3 |
0 | 300,000 |
부연 설명
- COL1은 속성별로 SUM 함수로 합산을 먼저 수행하고, 총주문금액에서 총 주문취소금액을 제외하였는데 주문취소금액이 한 건도 존재하지 않기에 합산한 결과는 Null이 됨, 즉 `300,000 - Null`을 수행하게 되고 결과로 Null 값을 반환
- COL2는 주문금액에서 주문취소금액을 제외한 결과를 SUM 함수로 합산하고, 최종결과가 Null일 경우 0을 반환하는 NVL 처리를 진행, 모든 행의 계산 결과가 Null 값을 반환하므로 최종적으로 NVL 함수를 수행했을 때 0을 반환
- COL3은 각 속성별로 SUM 함수로 합산하고 최종결과가 Null일 경우 0을 반환한 뒤, 총주문금액에서 총주문취소금액을 제외함, 이를 수행하면 최종적으로 `300,000 - 0`이 되며, 결과로 300,000을 반환하게 되어 원하는 결과를 얻을 수 있음
집계함수의 경우 Null 값을 제외한다는 특성을 이해하여야만 올바른 결과를 출력한다는 것을 숙지하기 위해 문제 하나를 더 풀어보겠습니다.
주문 모델에 또 다른 데이터를 입력했으며 주문취소금액의 평균을 구하기 위해 다음 SQL을 수행했습니다.
- 평균을 구하는 공식은 (자료 전체의 합) / (자료의 개수)
주문번호 | 주문금액 | 주문취소금액 |
1100001 | 100,000 | 20,000 |
1100002 | 15,000 | |
1100003 | 40,000 | 10,000 |
1100004 | 45,000 | 10,000 |
1100005 | 100,000 | 10,000 |
COL1 | COL2 |
10,000 | 12,500 |
부연 설명
- COL1은 주문취소금액의 합계를 총건수로 나누었으며 익히 알고 있는 평균을 구하는 공식으로 `50,000 / 5`의 연산 결과로 10,000을 반환함
- COL2는 평균값을 구하는 집계함수 AVG를 사용하였고 집계함수는 Null 값을 제외한다는 특성으로 `50,000 / 4`로 연산하였는데 이는 주문취소금액이 Null인 주문번호 1100002 데이터를 제외한 것, 따라서 12,500을 반환
- 원하는 평균값이 주문취소금액이 발생한 주문만을 대상으로 해야 하는지, 아니면 전체를 대상으로 해야 하는지에 대한 정의가 먼저 정해져야 올바른 값을 구할 수 있음
- 속성에 Null 값이 존재한다면 이처럼 많은 사항을 고려해야 하기 때문에 모델을 생성할 때, 업무를 정확히 파악하여 Null 허용 여부를 판단해야 함
참고
SQL 전문가 가이드 2020 개정판 - 한국데이터산업진흥원
반응형
'DB > SQL 전문가 가이드' 카테고리의 다른 글
[과목 II 1장 1절] 관계형 데이터베이스 개요 (0) | 2025.03.22 |
---|---|
[과목 I 2장 5절] 본질식별자 vs. 인조식별자 (0) | 2025.03.17 |
[과목 I 2장 3절] 모델이 표현하는 트랜잭션의 이해 (0) | 2025.03.17 |
[과목 I 2장 2절] 관계와 조인의 이해 (1) | 2025.03.17 |
[과목 I 2장 1절] 정규화 (0) | 2025.03.17 |