CodeGym /행동 /SQL SELF /PARTITION BY를 사용해서 데이터를 그룹으로 나누기

PARTITION BY를 사용해서 데이터를 그룹으로 나누기

SQL SELF
레벨 29, 레슨 3
사용 가능

상상해봐, 너가 큰 레스토랑에서 웨이터(아니면 커피 좋아하면 바리스타)로 일하고 있다고 치자. 매일 팁 얼마 벌었는지 정산하는데, 레스토랑이 여러 구역으로 나뉘어 있어서 각 구역별로 팁이 얼마인지 궁금한 거지. 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 쓸 때 순서 신경 써야 해!

2
과제
SQL SELF, 레벨 29, 레슨 3
잠금
지역별 판매 합계
지역별 판매 합계
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION