SQL 윈도우 함수, 개념부터 실전까지 한눈에! 🚀 PARTITION BY, ORDER BY, RANK()를 활용해 부서별 급여 순위 분석 & 데이터 집계까지 완벽 마스터하세요!
SQL 왕초보 가이드 - 3단계: 윈도우 함수 활용 🎯
"부서별 최고 급여를 받는 직원을 찾고 싶은데, 어떻게 해야 하죠?" 🤔
이런 고민을 해결할 수 있도록, 오늘은 SQL 윈도우 함수 기법을 배워볼 거예요! 🚀
1️⃣ 윈도우 함수(Window Function)란?
👉 특정 그룹 안에서 순위를 매기거나, 누적 합계를 실시간으로 계산하는 SQL 함수!
- 서브쿼리는 "전체 데이터를 다 조회한 후" 원하는 값을 찾는 방식이라면,
- 윈도우 함수는 "각 행을 처리하면서" 특정 값을 실시간으로 계산하는 방식이에요! 📚✨
2️⃣ 윈도우 함수의 핵심 문법 3가지!
🔹 PARTITION BY → 그룹 나누기 (GROUP BY와 비슷한 역할!)
- 데이터를 어떤 기준으로 묶을지 정하는 거예요. (예: 부서별, 카테고리별 등)
- 📌 비유: "이 도서관 책들을 장르별로 나누고 싶어!"
🔹 ORDER BY → 그룹 내 정렬
- 그룹 안에서 어떤 순서로 정렬할지 결정! (예: 높은 급여순, 최근 날짜순 등)
- 📌 비유: "장르별로 나눈 후, 책을 페이지 수 순으로 정렬해!"
🔹 RANK() → 순위 매기기
- 정렬된 데이터에 순위를 부여하는 함수!
- 📌 비유: "이제 책마다 몇 번째로 긴 책인지 번호를 붙이자!"
💡 간단한 윈도우 함수 예제
초보자도 쉽게 이해할 수 있도록 간단한 예제를 살펴볼까요? 🎯
📌 예제: 각 직원의 급여가 회사 전체에서 몇 번째로 높은지 확인하기
SELECT employee_name, salary,
RANK() OVER (ORDER BY salary DESC) AS salary_rank
FROM employees;
✅ 설명:
ORDER BY salary DESC
→ 급여가 높은 순서대로 정렬RANK() OVER (...)
→ 각 직원의 급여 순위를 계산
📌 결과 예시:
employee_name | salary | salary_rank |
---|---|---|
Alice | 8000 | 1 |
Bob | 7500 | 2 |
Charlie | 7500 | 2 |
David | 7000 | 4 |
💡 동일한 급여를 가진 직원이 있을 경우, 같은 순위를 부여하며 다음 순위가 건너뛰는 방식(RANK()
)을 사용합니다!
💡 순위 건너뛰기 없이 연속적으로 부여하고 싶다면 DENSE_RANK()
를 사용하면 됩니다!
💡 PARTITION BY를 활용한 예제
📌 예제: 각 부서별 직원의 급여 순위를 매기기
SELECT employee_name, department_id, salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS department_salary_rank
FROM employees;
✅ 설명:
PARTITION BY department_id
→ 각 부서별로 데이터를 나눔ORDER BY salary DESC
→ 부서 내에서 급여가 높은 순서대로 정렬RANK() OVER (...)
→ 부서별 급여 순위를 매김
📌 결과 예시:
employee_name | department_id | salary | department_salary_rank |
---|---|---|---|
Alice | 1 | 8000 | 1 |
Bob | 1 | 7500 | 2 |
Charlie | 2 | 9000 | 1 |
David | 2 | 8500 | 2 |
💡 이렇게 하면 각 부서별로 직원들의 급여 순위를 쉽게 확인할 수 있습니다! 🚀
🎯 PARTITION BY
와 GROUP BY
의 차이점은?
둘 다 데이터를 그룹화하는 기능이 있지만, 사용 방식과 결과가 완전히 다릅니다! 😲
GROUP BY |
PARTITION BY |
|
---|---|---|
기능 | 데이터를 집계(aggregation)해서 줄여줌. | 데이터를 그룹화하지만 행을 유지함. |
결과 | 한 그룹당 한 줄만 남음. | 각 그룹 내에서 모든 행을 유지하면서 계산을 추가함. |
대표 예제 | SUM() , AVG() , COUNT() 같은 집계 함수와 함께 사용. |
RANK() , AVG() OVER() 같은 윈도우 함수와 함께 사용. |
출력 데이터 | 개별 행이 사라지고 집계된 결과만 남음. | 기존 행이 유지되면서 추가 연산 결과가 붙음. |
🏆 직접 비교하면서 이해해보기!
❌ GROUP BY
만 사용한 경우 (개별 직원 데이터가 사라짐!)
SELECT department_name, AVG(salary) AS avg_salary
FROM employees
GROUP BY department_name;
department_name | avg_salary |
---|---|
IT | 6500 |
HR | 5250 |
✔ 부서별 평균 급여(avg_salary
)는 나오지만, 개별 직원 데이터는 없어졌어요! 😱
✅ PARTITION BY
를 사용한 경우 (개별 직원 정보 유지!)
SELECT department_name, employee_name, salary,
AVG(salary) OVER (PARTITION BY department_name) AS avg_salary
FROM employees;
department_name | employee_name | salary | avg_salary |
---|---|---|---|
IT | 김철수 | 7000 | 6500 |
IT | 박영희 | 6000 | 6500 |
HR | 이민호 | 5500 | 5250 |
HR | 최지우 | 5000 | 5250 |
✔ GROUP BY
없이도 개별 직원 데이터가 유지되면서 부서별 평균 급여(avg_salary
)가 표시됩니다! 🎉
🚀 PARTITION BY
+ GROUP BY
= 강력한 조합!
✔ GROUP BY
는 데이터를 집계해서 요약하는 역할을 해요. (즉, 개별 데이터가 사라짐!)
✔ PARTITION BY
는 그룹을 나누면서도 개별 데이터를 유지하는 역할을 합니다!
💡 그럼, 이 둘을 함께 사용하면?
GROUP BY
로 데이터를 그룹화하면서PARTITION BY
를 활용해 그룹 내 개별 데이터를 유지하면서 추가 분석이 가능해요! 🎯
🏢 예제: employees
테이블에서 부서별 급여 분석하기
다음 SQL 쿼리는 부서별 직원 수, 평균 급여, 최고·최저 급여를 계산하면서, 부서별 평균 급여 순위를 매깁니다! 🔥
SELECT department_name,
COUNT(employee_id) AS employee_count,
AVG(salary) AS avg_salary,
MAX(salary) AS max_salary,
MIN(salary) AS min_salary,
RANK() OVER (PARTITION BY department_name ORDER BY AVG(salary) DESC) AS avg_salary_rank
FROM employees
GROUP BY department_name;
📌 쿼리 설명
1️⃣ GROUP BY department_name
→ 부서별로 데이터를 그룹화하여 직원 수, 평균 급여, 최고·최저 급여 계산
COUNT(employee_id)
: 부서별 직원 수AVG(salary)
,MAX(salary)
,MIN(salary)
: 급여 통계 정보
2️⃣ RANK() OVER (PARTITION BY department_name ORDER BY AVG(salary) DESC)
PARTITION BY department_name
: 부서별로 나누고ORDER BY AVG(salary) DESC
: 평균 급여 기준으로 순위를 매김
📊 실행 결과 예시
department_name | employee_count | avg_salary | max_salary | min_salary | avg_salary_rank |
---|---|---|---|---|---|
IT | 2 | 85,000.00 | 90,000.00 | 80,000.00 | 1 |
HR | 2 | 52,500.00 | 55,000.00 | 50,000.00 | 2 |
Sales | 2 | 65,000.00 | 70,000.00 | 60,000.00 | 3 |
💡 즉, GROUP BY
로 요약된 데이터에서 PARTITION BY
를 활용하면 추가 분석이 가능해져요! 🎯
📢 SQL 데이터 분석할 때, 두 개를 함께 사용하면 더 강력한 인사이트를 얻을 수 있습니다! 🚀
3️⃣ 급여가 높은 상위 3명 직원 조회 (LIMIT 활용)
✅ 목표:
- 회사에서 가장 높은 급여를 받는 직원 상위 3명 조회
📌 예제 테이블 스키마
CREATE TABLE employees (
employee_id INT PRIMARY KEY,
employee_name VARCHAR(50),
salary INT
);
📌 기대 결과
employee_name | salary |
---|---|
Charlie | 8000 |
Alice | 7000 |
David | 7500 |
📌 SQL 정답
SELECT employee_name, salary
FROM employees
ORDER BY salary DESC
LIMIT 3;
✅ 설명:
ORDER BY salary DESC
→ 급여를 내림차순 정렬LIMIT 3
→ 급여가 가장 높은 상위 3명만 출력!
📌 같은 급여를 가진 직원도 포함하려면?
SELECT employee_name, salary,
DENSE_RANK() OVER(ORDER BY salary DESC) AS salary_rank
FROM employees
WHERE salary_rank <= 3;
✅ DENSE_RANK()
를 사용하면 동일한 급여를 가진 직원도 포함됩니다! 🏆
4️⃣ 부서별 최고 급여 직원 조회 (윈도우 함수 활용)
✅ 목표:
- 부서별 최고 급여를 받는 직원을 윈도우 함수로 더 빠르게 조회
WITH
키워드를 활용해봐요!
📌 예제 테이블 스키마
CREATE TABLE employees (
employee_id INT PRIMARY KEY,
employee_name VARCHAR(50),
department_id INT,
salary INT
);
CREATE TABLE departments (
department_id INT PRIMARY KEY,
department_name VARCHAR(50)
);
📌 기대 결과 (동일)
department_name | employee_name | max_salary |
---|---|---|
HR | Alice | 7000 |
IT | Charlie | 8000 |
📌 SQL 정답
WITH ranked_salaries AS (
SELECT d.department_name, e.employee_name, e.salary,
RANK() OVER (PARTITION BY d.department_id ORDER BY e.salary DESC) AS rnk
FROM employees e
JOIN departments d ON e.department_id = d.department_id
)
SELECT department_name, employee_name, salary AS max_salary
FROM ranked_salaries
WHERE rnk = 1;
✅ 설명:
RANK() OVER(PARTITION BY department_id ORDER BY salary DESC)
→ 각 부서별 급여 순위를 매김WHERE rnk = 1
→ 부서별 최고 급여를 받은 직원만 필터링! 🚀- WITH 키워드를 통해 employees와 departments 테이블을 조회한 후에, 완성된 임시 테이블을 기반으로 필터링 처리를 하기 때문에, 테이블 중복 스캔이 일어나지 않아 효율적임
🎯 윈도우 함수 활용 마무리!
오늘 배운 개념들 정리해볼까요? 🚀
✅ 윈도우 함수 (Window Function)
PARTITION BY
,ORDER BY
,RANK()
등을 활용해 그룹별 순위를 계산하는 강력한 기능- 서브쿼리보다 성능이 좋고, 더 쉽게 데이터를 다룰 수 있음
🔥 SQL 실력 레벨업! 자주 묻는 질문 (FAQ)
❓ Q. PARTITION BY와 GROUP BY는 어떻게 다를까요?
💡 GROUP BY는 데이터를 묶어서 집계 결과만 남기는 반면, PARTITION BY는 원본 데이터를 유지하면서 그룹별 분석이 가능합니다!
-- PARTITION BY: 원본 데이터를 유지하며 그룹별 평균 구하기
SELECT 사원명, 부서, 급여,
AVG(급여) OVER(PARTITION BY 부서) AS 부서별_평균급여
FROM 직원;
-- GROUP BY: 데이터를 묶어서 요약된 값만 출력
SELECT 부서, AVG(급여) AS 부서별_평균급여
FROM 직원
GROUP BY 부서;
📌 차이점 요약!
GROUP BY | PARTITION BY | |
---|---|---|
목적 | 데이터를 묶어 하나의 값으로 요약 | 데이터를 유지하면서 그룹별 연산 |
결과 행 개수 | 기존보다 줄어듦 | 기존과 동일 |
사용 예시 | 평균 급여를 출력 (부서별 1개 행) | 평균 급여를 출력 (각 사원별 행 유지) |
📌 다음 가이드에서는 SQL 성능 최적화와 인덱스를 활용하는 방법을 배울 예정이에요!
데이터가 많아도 빠르게 조회하는 법, 궁금하지 않나요? 😆🚀
'SQL 왕초보 가이드' 카테고리의 다른 글
[SQL 03-1] 서브쿼리 최적화 | 성능을 10배 높이는 실전 가이드 🚀 (0) | 2025.02.06 |
---|---|
[SQL 02] GROUP BY & 집계 함수 완벽 가이드 | 데이터 분석을 위한 필수 SQL 📊 (0) | 2025.02.06 |
[SQL 01] JOIN 쉽게 이해하기 | 초보자를 위한 SQL 기초 강좌 📊 (0) | 2025.02.06 |