위의 모델에서 주문금액과 주문취소금액은 Null 허용인 걸 알 수 있다.
IE표기법에서는 Null 허용 여부를 알 수 없지만, 바커 표기법에서는 속성 앞에 동그라미가 Null 허용 속성임을 의미한다.
위의 표는 주문 모델에 들어 있는 데이터이다.
본데이터를 바탕으로 다음 SQL의 결과를 예측해보자.
COL1, COL2, COL3는 최종 주문금액을 구하는 산식이다.
위의 결과는 모두 동일할까?
결과를 보면 Null 값이 포함되었을 경우 모두 결과가 다르게 출력하는 것을 알 수 있다.
이유는, Null 값의 연산은 언제나 Null이기 때문이다.
Null값은 연산이 불가능하다. 그래서 늘 Null값을 반환한다.
Null값으로 가능한 연산은 'IS NULL, IS NOT NULL' 밖에 없다.
또한 위 SQL를 알기 위해서는 NVL 함수를 알아야 한다. NVL 함수는 첫 번째 인자값의 결과가 Null일 경우 두 번째 인자 값을 반환하는 함수다.
COL1은 최종주문금액을 구하기 위해 Null값을 고려하지 않고, 주문금액에서 주문취소금액을 제외한 방식이다. Null 값이 존재하지 않는 첫 번째 행의 정삭적인 결과 '100,000 - 20,000 = 80,000'이 나오겠지만, Null 값이 존재하는 두 번째 행의 결과는 '15,000 - Null = Null'이라는 Null 값을 반환한다.
COL2는 주문금액에서 주문취소금액을 제외한 결과에 대해 NVL 처리를 하였다.
첫 행의 결과는 정상적으로 '100,000 - 20,000 = 80,000'이 나온다. 하지만 두 번째 결과는 '15,000 - Null = Null'로 Null 값을 반환한다. 이는 NVL 함수로 인하여 Null 값이 0으로 변환하여 반환하기 때문이다.
COL3은 각 속성별로 NVL 처리를 하고, 이후 주문금액에서 주문취소금액을 제외하였다. Null 값에 대한 이해를 숙지한 경우로 볼 수 있다. 첫 번째 행의 결과는 정상적으로 나온다. Null 값을 보유한 두 번째 행의 경우는 속성별로 Null일 경우 NVL 함수를 사용해 0으로 변환 후 연산을 처리하였다. 그리하여 '15,000 - 0 = 15,000'이라는 결과가 나오게 된다.
위의 표는 주문 모델에 다른 데이터를 입력한 것이다. 주문취소금액은 모두 Null 값으로 취소된 주문이 없는 상태다. 본 데이터를 바탕으로 다음 SQL 결과를 예측해보자.
COL1, COL2, COL3는 최종주문금액 총합을 구하는 산식이다.
이의 결과는 모두 동일할까?
위의 표는 SQL문의 결과이다. 모두 다른 결과를 출력한다. 집계함수는 Null 값의 경우는 제외하고 연산한다. SUM 함수는 정의된 칼럼의 값을 모두 합산하는 함수로서 Null 값이 들어올 경우 이는 제외하고 처리한다.
COL1은 속성별로 SUM 함수로 합산을 먼저 수행한 후, 총주문금액에서 총주문취소금액을 제외하였다. 주문취소금액은 한 건도 존재하지 않기에 '300,000 - Null'을 수행하게 되어 Null 값을 결과로 반환한다.
COL2는 주문금액에서 주문취소금액을 제외한 결과를 SUM 함수로 합산하고, 최종결과가 Null일 경우 0을 반환하는 NVL 처리를 하였다. 첫 번째 행은 '100,000 - Null'을 하여 결과로 Null 값을 반환한다. 두 번째 행도 '15000 - Null'을 수행하여 결과로 Null 값을 반환한다. 세 번째, 네 번째, 다섯 번째 모두 같은 결과로 Null 값을 반환하여, 이를 합산한 결과는 Null이 된다. 최종적으로 NVL 함수를 수행하여 Null을 0으로 변환하여 결과로 반환한다.
COL3은 각 속성별로 SUM 함수로 합산하고 최종결과가 Null일 경우 0을 반환한 후, 총주문금액에서 총주문취소금액을 제외하였다. 이는 NVL(SUM(주문금액),0)은 주문금액을 모두 합산하고, 합산한 결과가 Null일 경우 0을 반환하라는 의미이다. 주문취소금액 또한 이를 실행한다. 최종적으로 '300,000 - 0'이 되며, 결과로 300,000를 반환하여 원하는 결과를 얻을 수 있다.
위의 표는 주문 모델에 또 다른 데이터를 입력한 것이다. 주문최소금액의 평균은 얼마일까?
위와 같은 SQL에서 COL1과 COL2의 결과는 다르게 나온다.
COL1은 주문취소금액의 합계를 총건수로 나누었다. '50,000/5'의 연산 결과로 10,000을 반환하였다.
COL2는 평균값을 구하는 집계함수 AVG를 사용하였다. 집계함수는 Null 값을 제외한다는 특성으로 '50,000/4'로 연산하였다. 그 결과로 12,500을 반환하였다.
모델을 생성할 때 속성의 의미를 정확히 파악하고 Null 값을 허용하였는지, 아니면 너무 쉽게 Null 값을 허용해 Null에 대한 관리비용을 증가시킨 것은 아닌지 다시 한번 생각해 보아야 할 것이다.