처음 보면 윈도우 함수랑 집계 함수가 비슷해 보여. 둘 다 합계, 평균, 순위 같은 계산을 하니까. 근데 실제로는 꽤 다르거든? 그 차이를 제대로 파헤쳐보자.
집계 함수 (GROUP BY)
집계 함수는 이렇게 동작해:
- 지정한 컬럼으로 행들을 그룹핑해.
- 그룹핑 후에 각 그룹이 결과에서 한 줄로 바뀌어.
- 예시: 각 지역별로 총 매출을 알고 싶을 때.
SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;
특징: GROUP BY는 데이터를 "압축"해. 그룹에 속한 모든 행이 사라지고, 집계 결과만 남아.
윈도우 함수 (PARTITION BY)
윈도우 함수는 반대로:
- 원래 데이터 구조를 그대로 유지해 (행이 사라지거나 압축되지 않아!).
- "윈도우" — 논리적으로 나눈 그룹 안에서 계산을 할 수 있어.
예시: 각 도시가 자기 지역 전체 매출에서 차지하는 비율을 알고 싶은데, 데이터는 다 남겨두고 싶을 때.
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales_data;
특징: 윈도우 함수를 쓰면 행이 사라지지 않고, 각 행에 계산된 값이 추가돼.
예시: SUM() + GROUP BY vs SUM() + PARTITION BY
차이를 더 확실히 보려면, SUM()이 두 경우에 어떻게 동작하는지 보자. 예를 들어, sales_data 테이블이 이렇게 있다고 치자:
| region | city | sales |
|---|---|---|
| North | CityA | 100 |
| North | CityB | 150 |
| South | CityC | 200 |
| South | CityD | 250 |
GROUP BY로 합계 구하기
각 지역별로 총 매출을 알고 싶어:
SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;
결과는 이렇게 나와:
| region | total_sales |
|---|---|
| North | 250 |
| South | 450 |
무슨 일이 일어났냐면: region별로 행이 그룹핑되고, 각 그룹이 매출 합계 한 줄로 "압축"됐어.
PARTITION BY로 합계 구하기
이번엔 윈도우 함수로 똑같이 해보자:
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales_data;
결과:
| region | city | sales | total_sales_by_region |
|---|---|---|---|
| North | CityA | 100 | 250 |
| North | CityB | 150 | 250 |
| South | CityC | 200 | 450 |
| South | CityD | 250 | 450 |
무슨 일이 일어났냐면: PARTITION BY는 행을 "압축"하지 않아. 대신 각 윈도우(여기선 지역별) 안에서 합계를 계산해서 각 행에 붙여줘.
GROUP BY랑 PARTITION BY 언제 써야 할까?
GROUP BY: 최종 리포트에 딱이야
GROUP BY는 데이터 양을 줄이고, 그룹별로 결과만 뽑고 싶을 때 좋아. 예를 들면:
- 월별 총 매출.
- 상품 카테고리별 주문 개수 세기.
예시:
SELECT category, COUNT(*) AS total_orders
FROM orders
GROUP BY category;
PARTITION BY: 분석이나 상세 데이터에 최고
PARTITION BY는 모든 행을 남겨두고, 각 행마다 뭔가 계산해서 붙이고 싶을 때 써. 예를 들면:
- 카테고리별로 각 상품이 차지하는 매출 비율 구하기.
- 각 그룹 안에서 행 번호 매기기.
매출 비율 계산 예시:
SELECT
category,
product,
sales,
ROUND(
(sales * 100.0) / SUM(sales) OVER (PARTITION BY category),
2
) AS sales_percentage
FROM sales_data;
예시: 여러 윈도우 함수 한 번에 쓰기
윈도우 함수의 장점 중 하나는 여러 계산을 한 쿼리에서 할 수 있다는 거야. 예를 들어:
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales,
RANK() OVER (PARTITION BY region ORDER BY sales DESC) AS sales_rank
FROM sales_data;
결과:
| region | city | sales | total_sales | sales_rank |
|---|---|---|---|---|
| North | CityB | 150 | 250 | 1 |
| North | CityA | 100 | 250 | 2 |
| South | CityD | 250 | 450 | 1 |
| South | CityC | 200 | 450 | 2 |
GROUP BY보다 윈도우 함수가 좋은 점
원본 데이터 보존: GROUP BY는 행을 "압축"하지만, 윈도우 함수는 테이블 구조를 그대로 남겨둬.
한 쿼리에서 여러 계산 가능: PARTITION BY랑 ORDER BY를 다르게 줘서 여러 윈도우 함수를 한 번에 쓸 수 있어.
분석의 유연성: 윈도우 함수로 누적 합계, 순위, 비율 계산 등 원하는 대로 분석할 수 있어.
유연성 예시
여러 함수 조합해보자:
SELECT
region,
city,
sales,
SUM(sales) OVER (PARTITION BY region) AS total_sales,
AVG(sales) OVER (PARTITION BY region) AS avg_sales,
RANK() OVER (PARTITION BY region ORDER BY sales DESC) AS rank
FROM sales_data;
결과:
| region | city | sales | total_sales | avg_sales | rank |
|---|---|---|---|---|---|
| North | CityB | 150 | 250 | 125.0 | 1 |
| North | CityA | 100 | 250 | 125.0 | 2 |
| South | CityD | 250 | 450 | 225.0 | 1 |
| South | CityC | 200 | 450 | 225.0 | 2 |
제한사항과 흔한 실수
많이 하는 실수 중 하나가, 데이터를 "압축"해야 할 때 PARTITION BY를 쓰는 거야. 예를 들어, 이 쿼리 대신:
SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;
이렇게 쓰는 경우가 있어:
SELECT
region,
SUM(sales) OVER (PARTITION BY region) AS total_sales
FROM sales_data;
근데 이렇게 하면 모든 행이 다 나와. 데이터 양이 줄지 않지 (항상 원하는 결과가 아니야).
이제 GROUP BY랑 윈도우 함수 언제 써야 할지 확실히 알겠지? 이건 마치 망치랑 드라이버 중에 뭐 쓸지 고르는 거랑 비슷해. 둘 다 못 박을 수 있지만... 방식이 달라!
GO TO FULL VERSION