MySQL에서 그룹별로 데이터를 집계할 때, 해당 그룹에 NULL 값이 하나라도 포함되어 있으면 합계를 계산하지 않고 제외하고 싶은 경우가 있습니다. 즉, 모든 행의 값이 정상적으로 존재할 때만 SUM 결과를 얻는 것이죠. 이런 요구사항은 GROUP BY 절과 HAVING 절을 함께 사용하면 손쉽게 해결할 수 있습니다.
기본 문법
SELECT yourColumnName1, SUM(yourColumnName2) FROM yourTableName GROUP BY yourColumnName1 HAVING COUNT(yourColumnName2) = COUNT(*);
핵심은 HAVING 절에서 COUNT(컬럼명)과 COUNT(*)를 비교하는 것입니다. COUNT 함수는 NULL 값을 세지 않기 때문에, 컬럼에 NULL이 하나라도 존재하면 두 카운트 값이 달라지고, 해당 그룹은 HAVING 조건을 통과하지 못해 결과에서 자동으로 제외됩니다.
예제 테이블 생성
먼저 예제로 사용할 테이블을 만들어 보겠습니다.
mysql> create table SumDemo -> ( -> Id int, -> Amount int -> ); Query OK, 0 rows affected (0.58 sec)
데이터 삽입
insert 명령으로 여러 개의 레코드를 추가합니다. 이때 일부러 Id 2번 그룹에는 NULL 값을 포함시켰습니다.
mysql> insert into SumDemo values(1,200); Query OK, 1 row affected (0.22 sec) mysql> insert into SumDemo values(2,100); Query OK, 1 row affected (0.19 sec) mysql> insert into SumDemo values(2,NULL); Query OK, 1 row affected (0.14 sec) mysql> insert into SumDemo values(1,300); Query OK, 1 row affected (0.16 sec) mysql> insert into SumDemo values(2,100); Query OK, 1 row affected (0.17 sec) mysql> insert into SumDemo values(1,500); Query OK, 1 row affected (0.16 sec)
전체 데이터 확인
select 문으로 테이블의 모든 레코드를 조회해 보겠습니다.
mysql> select *from SumDemo;
출력 결과
+------+--------+ | Id | Amount | +------+--------+ | 1 | 200 | | 2 | 100 | | 2 | NULL | | 1 | 300 | | 2 | 100 | | 1 | 500 | +------+--------+ 6 rows in set (0.00 sec)
NULL이 없는 그룹만 합계 구하기
이제 모든 행이 NULL이 아닌 그룹에 대해서만 합계를 구하는 쿼리입니다.
mysql> select Id, -> SUM(Amount) -> from SumDemo -> GROUP BY ID -> HAVING COUNT(Amount) = COUNT(*);
실행 결과
Id 2번 그룹에는 NULL 값이 포함되어 있어 COUNT(Amount)가 COUNT(*)보다 작습니다. 따라서 HAVING 조건을 통과하지 못하고 결과에서 완전히 제외되었습니다. 반면 Id 1번 그룹의 값들은 모두 정상이므로 합계가 계산됩니다. 즉, 200 + 300 + 500 = 1000이 됩니다.
+------+-------------+ | Id | SUM(Amount) | +------+-------------+ | 1 | 1000 | +------+-------------+ 1 row in set (0.09 sec)
정리
COUNT(컬럼) = COUNT(*) 비교를 통해 NULL 포함 여부를 판단하는 방식은 간단하면서도 강력합니다. 참고로, NULL이 있는 그룹도 목록에는 남기면서 합계 값만 NULL로 표시하고 싶다면 CASE 표현식을 SUM과 함께 활용하는 방법도 고려해 볼 수 있습니다.