SQL에서 데이터 순위 매기는 방법: 윈도우 함수 소개
Ethan Miller
Product Engineer · Leapcell

Key Takeaways
- SQL은 데이터를 정렬하고 분석하기 위한 여러 순위 함수를 제공합니다.
- 동점 항목을 처리하는 방법에 따라 적절한 함수를 선택하세요.
- 특정 그룹 내에서 순위를 매기려면
PARTITION BY
를 사용하세요.
Introduction
SQL에서 순위 매기기는 데이터를 정렬하고, 동점 항목을 처리하며, 위치에 따라 결과를 필터링하는 데 필수적입니다. SQL은 이러한 목표를 달성하기 위해 여러 윈도우 함수(ROW_NUMBER()
, RANK()
, DENSE_RANK()
, NTILE()
)를 제공합니다. 각각은 약간 다른 사용 사례에 적합합니다.
1. ROW_NUMBER()
-
동점 항목을 고려하지 않고 각 행에 고유한 순차 번호를 할당합니다.
-
구문:
ROW_NUMBER() OVER ( [PARTITION BY partition_expr] ORDER BY order_expr [ASC|DESC] ) AS row_num
-
예제: 점수 내림차순으로 고유한 행 번호 할당:
SELECT student_name, score, ROW_NUMBER() OVER (ORDER BY score DESC) AS row_num FROM students;
2. RANK()
-
동점 값에 동일한 순위를 할당하지만, 후속 순위에 간격이 생깁니다.
-
구문:
RANK() OVER ( [PARTITION BY partition_expr] ORDER BY order_expr [ASC|DESC] ) AS rank
-
예제: 학생 순위 매기기, 간격 허용:
SELECT student_name, score, RANK() OVER (ORDER BY score DESC) AS rank FROM students;
두 학생이 최고 점수를 공유하는 경우, 둘 다 1위가 되고 다음은 3위가 됩니다.
3. DENSE_RANK()
-
RANK()
와 유사하지만, 동점 후 간격을 두지 않습니다. -
구문:
DENSE_RANK() OVER ( [PARTITION BY partition_expr] ORDER BY order_expr [ASC|DESC] ) AS dense_rank
-
예제:
SELECT student_name, score, DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank FROM students;
두 학생이 공동 1위를 하는 경우, 둘 다 1위가 되고 다음은 2위가 됩니다.
4. NTILE(N)
-
행을 N개의 버킷으로 나누고 1부터 N까지의 버킷 번호를 할당합니다.
-
구문:
NTILE(N) OVER ( [PARTITION BY partition_expr] ORDER BY order_expr [ASC|DESC] ) AS tile
-
예제:
SELECT student_name, score, NTILE(4) OVER (ORDER BY score DESC) AS quartile FROM students;
학생들을 점수별로 4개의 그룹으로 나눕니다.
5. Partitioning
-
PARTITION BY
는 그룹 내에서 순위를 매길 수 있습니다 (예: 부서 또는 과목별). -
예제: 각 반 내에서 학생 순위 매기기:
SELECT class, student_name, score, RANK() OVER ( PARTITION BY class ORDER BY score DESC ) AS class_rank FROM students;
6. Why Choose One?
Function | Handles Ties | Gaps After Ties | Use Case |
---|---|---|---|
ROW_NUMBER() | No | No (always 1,2,3...) | When each row must be uniquely numbered |
RANK() | Yes | Yes | When ties share rank and gaps are acceptable |
DENSE_RANK() | Yes | No | When ties share rank, but gaps are not allowed |
NTILE(N) | N/A | N/A | When dividing rows into equal-sized buckets |
7. Filtering Top‑N Results
상위 3명의 학생을 RANK()
를 사용하여 가져오려면:
WITH ranked AS ( SELECT student_name, score, RANK() OVER (ORDER BY score DESC) AS rank FROM students ) SELECT student_name, score FROM ranked WHERE rank <= 3;
이 쿼리는 동점 항목을 포함합니다. 정확히 3개의 행을 원하십니까? 대신 ROW_NUMBER()
를 사용하세요.
8. Real-World Examples
-
제품별 매장별 판매:
SELECT product, store_id, sales, RANK() OVER ( PARTITION BY product ORDER BY sales DESC ) AS sales_rank FROM sales_data;
제품별 최고 판매 매장을 식별하는 데 도움이 됩니다.
-
부서별 급여 분석:
WITH dept_ranked AS ( SELECT department_id, employee_name, salary, RANK() OVER ( PARTITION BY department_id ORDER BY salary DESC ) AS dept_rank FROM employees ) SELECT * FROM dept_ranked WHERE dept_rank = 1;
부서별 최고 급여 직원을 찾습니다.
9. Summary
- 동점 항목 처리 및 간격 기본 설정에 따라 윈도우 함수를 선택하세요.
- 그룹화를 위해
PARTITION BY
를 사용하세요. - 순위 로직을 정의하기 위해
ORDER BY
를 사용하세요. - 목표 결과를 위해
WHERE
또는 CTE를 사용하여 결과를 필터링하십시오.
FAQs
결과 집합 내에서 데이터를 정렬하고 분석하는 데 사용됩니다.
RANK()는 동점 후에 간격을 남깁니다. DENSE_RANK()는 그렇지 않습니다.
윈도우 함수에서 PARTITION BY 절을 사용하세요.
We are Leapcell, your top choice for hosting backend projects.
Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:
Multi-Language Support
- Develop with Node.js, Python, Go, or Rust.
Deploy unlimited projects for free
- pay only for usage — no requests, no charges.
Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the Documentation!
Follow us on X: @LeapcellHQ