상상해봐, 너가 큰 레스토랑에서 웨이터(아니면 커피 좋아하면 바리스타)로 일하고 있다고 치자. 매일 팁 얼마 벌었는지 정산하는데, 레스토랑이 여러 구역으로 나뉘어 있어서 각 구역별로 팁이 얼마인지 궁금한 거지. PARTITION BY는 SQL에서 "레스토랑을 구역별로 나누는" 역할을 해!
좀 더 공식적으로 말하면, PARTITION BY는 윈도우 함수에서 테이블의 모든 행을 여러 그룹(또는 "파티션")으로 나눌 때 써. 각 그룹 안에서 윈도우 함수가 따로따로 실행돼. 즉, 각 "파티션"마다 함수를 따로 적용하는 거랑 똑같아.
예시: 어떻게 동작하는지
예를 들어, sales라는 테이블에 판매 데이터가 있다고 해보자:
| region | salesperson | amount |
|---|---|---|
| North | Alice | 100 |
| North | Bob | 200 |
| South | Alice | 150 |
| South | Charlie | 250 |
각 지역(region)별로 각 판매자가 얼마 벌었는지 따로 계산하고 싶으면 PARTITION BY가 딱이야.
PARTITION BY 문법
문법은 진짜 간단해:
윈도우_함수() OVER (PARTITION BY 컬럼_또는_컬럼들)
윈도우_함수()— 예를 들면SUM(),AVG(),ROW_NUMBER()등등.PARTITION BY 컬럼— 어떤 컬럼 기준으로 행을 나눌지 정하는 거야.OVER()— SQL한테 "이 윈도우 안에서 뭔가 해봐"라고 알려주는 연산자야.
예시: 그룹별 합계
각 지역(region)별로 판매 합계를 계산해보자:
SELECT
region,
salesperson,
amount,
SUM(amount) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales;
결과는 이렇게 나와:
| region | salesperson | amount | total_sales_by_region |
|---|---|---|---|
| North | Alice | 100 | 300 |
| North | Bob | 200 | 300 |
| South | Alice | 150 | 400 |
| South | Charlie | 250 | 400 |
어떻게 된 거냐면, SQL이 region 컬럼 값(North, South)별로 행을 그룹으로 나누고, 각 그룹마다 SUM()을 따로 계산해. 그래서 "North" 그룹 안 행들은 합계가 똑같고, "South" 그룹도 마찬가지로 따로 합계가 나와.
PARTITION BY 활용 예시
실제 상황에서 PARTITION BY가 어떻게 유용한지 몇 가지 예를 들어볼게.
예시 1: 그룹 내 랭킹 매기기
각 지역(region)별로 판매자 순위를 매기고 싶다고 해보자. PARTITION BY랑 RANK() 함수를 같이 쓰면 돼:
SELECT
region,
salesperson,
amount,
RANK() OVER (PARTITION BY region ORDER BY amount DESC) AS rank_in_region
FROM sales;
결과:
| region | salesperson | amount | rank_in_region |
|---|---|---|---|
| North | Bob | 200 | 1 |
| North | Alice | 100 | 2 |
| South | Charlie | 250 | 1 |
| South | Alice | 150 | 2 |
RANK() 함수가 각 region 그룹 안에서 1부터 순위를 매겨줘. 각 그룹마다 랭킹이 1부터 시작하는 거지.
예시 2: 그룹 평균이랑 비교하기
각 판매자가 자기 지역 평균에 비해 얼마 벌었는지 보고 싶으면 AVG()를 쓰면 돼:
SELECT
region,
salesperson,
amount,
AVG(amount) OVER (PARTITION BY region) AS avg_sales_by_region,
amount - AVG(amount) OVER (PARTITION BY region) AS diff_from_avg
FROM sales;
결과:
| region | salesperson | amount | avg_sales_by_region | diff_from_avg |
|---|---|---|---|---|
| North | Alice | 100 | 150 | -50 |
| North | Bob | 200 | 150 | 50 |
| South | Alice | 150 | 200 | -50 |
| South | Charlie | 250 | 200 | 50 |
먼저 SQL이 region별로 행을 그룹으로 나누고, 각 그룹마다 AVG(amount)를 계산해. 그리고 각 행에서 자기 값이랑 평균이랑 차이도 계산해주는 거지.
예시 3: 그룹 내 행 번호 매기기
각 지역(region) 그룹 안에서 트랜잭션에 번호를 붙이고 싶으면 ROW_NUMBER()를 쓰면 돼:
SELECT
region,
salesperson,
amount,
ROW_NUMBER() OVER (PARTITION BY region ORDER BY amount DESC) AS row_number
FROM sales;
결과:
| region | salesperson | amount | row_number |
|---|---|---|---|
| North | Bob | 200 | 1 |
| North | Alice | 100 | 2 |
| South | Charlie | 250 | 1 |
| South | Alice | 150 | 2 |
GROUP BY랑 비교
PARTITION BY랑 GROUP BY 헷갈릴 때 많지? 둘이 어떻게 다른지 비교해보자:
GROUP BY
GROUP BY는 결과 구조 자체를 바꿔버려 — 테이블 행들이 집계로 바뀌는 거지. 예를 들어:
SELECT
region,
SUM(amount) AS total_sales
FROM sales
GROUP BY region;
결과:
| region | total_sales |
|---|---|
| North | 300 |
| South | 400 |
여기선 판매자 정보가 사라져버려. 데이터가 집계돼서 디테일이 없어지는 거지.
PARTITION BY
PARTITION BY는 반대로 구조를 안 바꿔. 각 행이 그대로 보이는데, 그룹별로 계산된 값이 추가로 붙는 거야. 즉, PARTITION BY는 디테일 안 잃고 집계할 수 있게 해줘.
PARTITION BY 쓸 때 자주 하는 실수
실수 1: PARTITION BY 빼먹음
가끔 데이터 그룹핑하려고 하는데 PARTITION BY를 깜빡할 때가 있어. 예를 들어:
SELECT
region,
salesperson,
amount,
SUM(amount) OVER () AS total_sales
FROM sales;
결과:
| region | salesperson | amount | total_sales |
|---|---|---|---|
| North | Alice | 100 | 700 |
| North | Bob | 200 | 700 |
| South | Alice | 150 | 700 |
| South | Charlie | 250 | 700 |
여기선 SUM(amount)가 테이블 전체 합계로 계산돼버려. 지역별로 따로 계산하고 싶으면 PARTITION BY region 꼭 써야 해.
실수 2: ORDER BY 순서 잘못 씀
RANK()나 ROW_NUMBER() 같은 함수 쓸 때 윈도우 안에서 행 순서가 중요해. OVER() 안에 ORDER BY 쓸 때 순서 신경 써야 해!
GO TO FULL VERSION