MySQL에서는 하나의 쿼리 안에서 GROUP BY, HAVING, ORDER BY 절을 함께 사용하여 그룹별 합계가 특정 범위에 속하는 레코드만 손쉽게 조회할 수 있습니다. 이번 글에서는 실제 예제를 통해 그 과정을 단계별로 살펴보겠습니다.
1. 테이블 생성하기
먼저 예제에 사용할 테이블을 생성합니다.
mysql> create table DemoTable
(
Id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
CustomerName varchar(20),
ProductPrice int
);
Query OK, 0 rows affected (0.70 sec)2. 샘플 데이터 삽입하기
INSERT 명령을 사용해 테이블에 레코드를 추가합니다.
mysql> insert into DemoTable(CustomerName,ProductPrice) values('Chris',600);
Query OK, 1 row affected (0.18 sec)
mysql> insert into DemoTable(CustomerName,ProductPrice) values('David',450);
Query OK, 1 row affected (0.09 sec)
mysql> insert into DemoTable(CustomerName,ProductPrice) values('Chris',980);
Query OK, 1 row affected (0.40 sec)
mysql> insert into DemoTable(CustomerName,ProductPrice) values('Mike',1200);
Query OK, 1 row affected (0.11 sec)
mysql> insert into DemoTable(CustomerName,ProductPrice) values('Chris',400);
Query OK, 1 row affected (0.11 sec)
mysql> insert into DemoTable(CustomerName,ProductPrice) values('David',1200);
Query OK, 1 row affected (0.20 sec)3. 전체 데이터 확인하기
SELECT 문으로 테이블에 저장된 모든 레코드를 조회해 보겠습니다.
mysql> select *from DemoTable;
실행 결과는 다음과 같습니다.
+----+--------------+--------------+ | Id | CustomerName | ProductPrice | +----+--------------+--------------+ | 1 | Chris | 600 | | 2 | David | 450 | | 3 | Chris | 980 | | 4 | Mike | 1200 | | 5 | Chris | 400 | | 6 | David | 1200 | +----+--------------+--------------+ 6 rows in set (0.00 sec)
4. GROUP BY와 HAVING으로 범위 조건 적용하기
고객 이름별로 상품 가격의 합계를 구한 뒤, 합계가 1600 이상 2000 이하인 그룹만 추출하고, 결과를 고객 이름 기준 내림차순으로 정렬하는 쿼리입니다.
mysql> select CustomerName,sum(ProductPrice) AS Total_Price
from DemoTable
group by CustomerName
having sum(ProductPrice) between 1600 and 2000
order by CustomerName DESC;실행 결과는 다음과 같습니다.
+--------------+-------------+ | CustomerName | Total_Price | +--------------+-------------+ | David | 1650 | | Chris | 1980 | +--------------+-------------+ 2 rows in set (0.00 sec)
쿼리 동작 원리 정리
이 쿼리가 처리되는 순서를 이해하면 더욱 명확합니다.
GROUP BY CustomerName — 고객 이름을 기준으로 레코드를 그룹화합니다. Chris(600 + 980 + 400 = 1980), David(450 + 1200 = 1650), Mike(1200) 세 개의 그룹이 만들어집니다.
HAVING sum(ProductPrice) BETWEEN 1600 AND 2000 — 각 그룹의 합계가 1600~2000 사이인 경우만 필터링합니다. Mike의 합계는 1200이므로 제외됩니다.
ORDER BY CustomerName DESC — 최종 결과를 고객 이름 기준 내림차순으로 정렬합니다.
참고로 WHERE 절은 그룹화 이전에 개별 행을 필터링하는 반면, HAVING 절은 GROUP BY로 집계된 이후의 결과에 조건을 적용한다는 점이 핵심 차이입니다. 따라서 SUM() 같은 집계 함수의 결과에 조건을 걸 때는 반드시 HAVING을 사용해야 합니다.