데이터를 행 단위로 조회하는 것을 넘어, 전체 데이터를 요약하고 의미 있는 그룹으로 묶어 통계를 내는 것은 데이터 분석의 핵심이다.
SQL은 이를 위해 집계 함수와 GROUP BY 절을 제공한다.
📌 집계 함수: 데이터를 한눈에 요약하기
집계 함수는 여러 행의 데이터를 바탕으로 하나의 요약된 결과 값을 계산해 주는 함수다.
- COUNT(): 행의 개수를 센다.
- COUNT(*): NULL을 포함한 테이블의 모든 행 개수를 반환한다. (예: 전체 주문 건수)
- COUNT(컬럼명): 해당 컬럼에서 NULL이 아닌 값의 개수만 반환한다. (예: 카테고리가 등록된 주문 건수)
- COUNT(DISTINCT 컬럼명): 중복을 제거한 고유한 값의 개수를 반환한다 (예: 실제 구매한 순수 고객 수)
- SUM(컬럼명): 숫자 컬럼의 합계를 계산한다. (예: 총매출액)
- AVG(컬럼명): 숫자 컬럼의 평균을 계산한다. (예: 평균 주문 금액)
- MAX(컬럼명) / MIN(컬럼명): 컬럼의 최댓값과 최솟값을 찾는다. (예: 가장 비싼 상품 가격, 최초 주문일)
📢 중요: SUM, AVG, MAX, MIN 함수는 계산 과정에서 NULL 값을 자동으로 제외한다.
📌 GROUP BY: 데이터를 의미 있는 그룹으로 묶기
GROUP BY 절은 특정 열(Column)의 값이 같은 행들을 하나의 그룹으로 묶어주는 역할을 한다.
이렇게 그룹화된 결과에 집계 함수를 적용하면, 전체 데이터가 아닌 '각 그룹에 대한 통계'를 낼 수 있다.
예를 들어, "고객별 주문 건수"를 알고 싶다면 customer_id 열을 기준으로 그룹화하고, 각 그룹의 행 개수를 세면 된다.
SELECT
customer_id,
COUNT(*) AS `고객별 주문 건수`
FROM
orders
GROUP BY
customer_id;
⚠️ GROUP BY 사용 시 핵심 규칙
- GROUP BY를 사용하면 SELECT 절에는 GROUP BY에 사용된 열이나 집계 함수만 올 수 있다.
- 그룹으로 묶으면 여러 행이 하나의 대표 행으로 요약되므로, 그룹 전체를 대표할 수 없는 개별 행의 정보는 조회할 수 없다.
📌 HAVING: 그룹에 대한 필터링
WHERE 절과 HAVING 절은 둘 다 필터링을 하지만, 작동 시점과 대상이 완전히 다르다.
- WHERE:
- 그룹화 전, 개별 행을 대상으로 필터링한다.
- 집계 함수를 사용할 수 없다.
- HAVING:
- 그룹화 후, 생성된 그룹을 대상으로 필터링한다.
- 집계 함수를 사용한 조건절을 사용할 수 있다.
-- 1번 상품을 2회 이상 주문한 고객 조회
SELECT
customer_id,
COUNT(*) AS `고객별 주문 건수`
FROM
orders
WHERE
product_id = 1
GROUP BY
customer_id
HAVING
COUNT(*) >= 2;
🧩 SQL의 논리적 실행 순서: 왜 WHERE에서 별칭을 못 쓸까?
우리가 SQL을 작성하는 순서와 데이터베이스가 실제로 쿼리를 처리하는 논리적 순서는 다르다.
이 순서를 이해하는 것은 복잡한 쿼리를 작성할 때 매우 중요하다.
SQL 논리적 실행 순서
- FROM: 대상 테이블을 지정한다.
- WHERE: 개별 행을 필터링한다.
- GROUP BY: 행들을 그룹으로 묶는다.
- HAVING: 그룹을 필터링한다.
- SELECT: 결과를 계산하고 열을 선택한다. → 이때 별칭(Alias)이 생성된다.
- ORDER BY: 결과를 정렬한다.
- LIMIT: 최종 반환할 행의 개수를 제한한다.
이 실행 순서 때문에 WHERE 절(2단계)에서는 아직 생성되지 않은 SELECT 절의 별칭(5단계)을 사용할 수 없다.
반면, ORDER BY 절(6단계)에서는 이미 생성된 SELECT 절의 별칭을 사용할 수 있다.
MySQL은 사용자의 편의를 위해 SQL 표준을 확장하여 HAVING 절에서 SELECT 절의 별칭을 사용할 수 있도록 허용한다.
'DB' 카테고리의 다른 글
| [DB] 외부 조인 (OUTER JOIN), 셀프 조인 (SELF JOIN), 크로스 조인 (CROSS JOIN) (0) | 2025.09.19 |
|---|---|
| [DB] 내부 조인 (INNER JOIN) (0) | 2025.09.17 |
| [DB] SQL – 문자열 함수, NULL 함수(IFNULL, COALESCE) (0) | 2025.09.17 |
| [DB] SQL – 조회, 필터링, 정렬 (WHERE, ORDER BY, LIMIT) (1) | 2025.09.17 |
| [DB] SQL – DDL, DML (0) | 2025.09.17 |