πŸ“Œμš”μ•½

μœˆλ„μš° ν•¨μˆ˜ 쀑 ν•˜λ‚˜μΈ μˆœμœ„ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄ κ²°κ³Ό μ§‘ν•©μ˜ 각 행에 μˆœμœ„λ₯Ό ν• λ‹Ήν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  RANK() DENSE_RANK() ROW_NUMBER()
동일 κ°’ 처리 동일 μˆœμœ„ λΆ€μ—¬ 동일 μˆœμœ„ λΆ€μ—¬ 각 행별 고유 μˆœμœ„ λΆ€μ—¬
μˆœμœ„ 간격 동일 μˆœμœ„μžˆλŠ” 경우,
κ·Έ λ‹€μŒ μˆœμœ„λŠ” 이전 동일 μˆœμœ„λ₯Ό κ°€μ§„ ν–‰ 수만큼의 간격 λ°œμƒ
동일 μˆœμœ„κ°€ μžˆμ–΄λ„,
μˆœμœ„λ₯Ό κ±΄λ„ˆλ›°μ§€ μ•Šκ³ (간격 없이) μ—°μ†λœ μˆœμœ„λ₯Ό λΆ€μ—¬
동일 μˆœμœ„κ°€ μžˆμ–΄λ„,
각 ν–‰μ—λŠ” 순차적으둜 μœ λ‹ˆν¬ν•œ μˆœμœ„ λΆ€μ—¬
μ˜ˆμ‹œ 1,2,2,4,5, ... 1,2,2,3,4, ... 1,2,3,4,5, ...

 


1. RANK() ν•¨μˆ˜

[MySQL Tutorial]
RANK() ν•¨μˆ˜λŠ” κ²°κ³Ό μ§‘ν•©μ˜ νŒŒν‹°μ…˜ λ‚΄ 각 행에 μˆœμœ„λ₯Ό ν• λ‹Ήν•©λ‹ˆλ‹€.
ν–‰μ˜ μˆœμœ„λŠ” 1에 κ·Έ μ•žμ— μ˜€λŠ” μˆœμœ„ 수λ₯Ό λ”ν•œ κ°’μœΌλ‘œ μ§€μ •λ©λ‹ˆλ‹€.

[Oracle Tutorial]
RANK() ν•¨μˆ˜λŠ” 각 μ§‘ν•©μ—μ„œ κ°’μ˜ μˆœμœ„λ₯Ό κ³„μ‚°ν•˜λŠ” 뢄석 ν•¨μˆ˜μž…λ‹ˆλ‹€.
RANK() ν•¨μˆ˜λŠ” λ™μΌν•œ 값을 κ°€μ§„ 행에 λŒ€ν•΄ λ™μΌν•œ μˆœμœ„λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. 동λ₯  μˆœμœ„μ— 동λ₯  ν–‰ 수λ₯Ό 더해 λ‹€μŒ μˆœμœ„λ₯Ό κ³„μ‚°ν•©λ‹ˆλ‹€. λ”°λΌμ„œ μˆœμœ„λŠ” μ—°μ†λœ μˆ«μžκ°€ 아닐 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.
RANK() ν•¨μˆ˜λŠ” μƒμœ„ N 및 ν•˜μœ„ N 쿼리에 μœ μš©ν•©λ‹ˆλ‹€.

 

RANK() ν•¨μˆ˜λŠ” μœˆλ„μš° ν•¨μˆ˜ 쀑 κ·Έλ£Ή λ‚΄ μˆœμœ„ ν•¨μˆ˜λ‘œ, νŠΉμ • μœˆλ„μš°(λΆ€λΆ„)λ‚΄μ—μ„œ μˆœμœ„λ₯Ό ν• λ‹Ήν•˜λŠ” 데 μ‚¬μš©ν•©λ‹ˆλ‹€.

λ™μΌν•œ 값을 κ°€μ§„ 행에 λŒ€ν•΄ λ™μΌν•œ μˆœμœ„λ₯Ό λΆ€μ—¬ν•˜κ³  κ·Έ λ‹€μŒ μˆœμœ„λŠ” 동일 μˆœμœ„λ₯Ό κ°€μ§„ ν–‰ 수만큼의 μ‹œν€€μŠ€ 간격이 μƒκΉλ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄ 3μœ„κ°€ 3λͺ…이라면, 1,2,3,3,3,6,7,8, ... μ΄λ ‡κ²Œ μˆœμœ„κ°€ λ§€κ²¨μ§‘λ‹ˆλ‹€.

 

RANK() 문법

MySQLκ³Ό Oracle의 RANK() ν•¨μˆ˜ 문법은 각각 μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

MySQL 

RANK() OVER (
	PARTITION BY <expression>[{,<expression>...}]
	ORDER BY <expression> [ASC|DESC], [{,<expression>...}]
)

Oracle

RANK() OVER ([query_partition_clause] order_by_clause)
  • PARTITION BY | query_partition_clause : κ²°κ³Ό 집합을 νŒŒν‹°μ…˜μœΌλ‘œ λ‚˜λˆ•λ‹ˆλ‹€.
    • μ˜΅μ…˜ 값이며, μƒλž΅ν•  경우 쑰회 결과의 λͺ¨λ“  행을 ν•˜λ‚˜μ˜ νŒŒν‹°μ…˜μœΌλ‘œ μ·¨κΈ‰ν•©λ‹ˆλ‹€.
  • ORDER BY | order_by_clause : ν•˜λ‚˜ μ΄μƒμ˜ μ—΄μ΄λ‚˜ ν‘œν˜„μ‹μ„ κΈ°μ€€μœΌλ‘œ νŒŒν‹°μ…˜ λ‚΄μ˜ 행을 μ •λ ¬ν•©λ‹ˆλ‹€.
    • ν•„μˆ˜ 값이며, ν•¨μˆ˜κ°€ μ μš©λ˜λŠ” 각 νŒŒν‹°μ…˜μ˜ ν–‰μ˜ 논리적인 μ •λ ¬ μˆœμ„œλ₯Ό κ²°μ •ν•©λ‹ˆλ‹€.

 

2. DENSE_RANK() ν•¨μˆ˜

[MySQL Tutorial]
DENSE_RANK() ν•¨μˆ˜λŠ” μˆœμœ„ 값에 차이 없이 νŒŒν‹°μ…˜ λ˜λŠ” κ²°κ³Ό μ§‘ν•© λ‚΄μ˜ 각 행에 μˆœμœ„λ₯Ό ν• λ‹Ήν•˜λŠ” μœˆλ„μš° ν•¨μˆ˜μž…λ‹ˆλ‹€.
ν–‰μ˜ μˆœμœ„λŠ” ν–‰ μ•žμ— μ˜€λŠ” κ³ μœ ν•œ μˆœμœ„ κ°’μ—μ„œ 1μ”© μ¦κ°€ν•©λ‹ˆλ‹€.

[Oracle Tutorial]
DENSE_RANK() ν•¨μˆ˜λŠ” μ •λ ¬λœ ν–‰ μ§‘ν•©μ—μ„œ ν–‰μ˜ μˆœμœ„λ₯Ό κ³„μ‚°ν•˜λŠ” 뢄석 ν•¨μˆ˜μž…λ‹ˆλ‹€.
RANK() ν•¨μˆ˜μ™€ 달리 DENSE_RANK() ν•¨μˆ˜λŠ” μˆœμœ„ 값을 μ—°μ†λœ μ •μˆ˜λ‘œ ν• λ‹Ήν•©λ‹ˆλ‹€. 동λ₯ μΈ κ²½μš°μ—λŠ” μˆœμœ„λ₯Ό κ±΄λ„ˆλ›°μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
μˆœμœ„ κΈ°μ€€ 값이 λ™μΌν•œ ν–‰μ—λŠ” λ™μΌν•œ μˆœμœ„ 값이 μ μš©λ©λ‹ˆλ‹€. 

 

DENSE_RANK() ν•¨μˆ˜λŠ” RANK() ν•¨μˆ˜μ™€ λ™μΌν•˜κ²Œ λ™μΌν•œ 값을 κ°€μ§„ 행에 λŒ€ν•΄ λ™μΌν•œ μˆœμœ„λ₯Ό λΆ€μ—¬ν•˜μ§€λ§Œ κ·Έ λ‹€μŒμ— λ‚˜μ˜€λŠ” ν–‰μ—λŠ” μˆœμœ„λ₯Ό κ±΄λ„ˆλ›°μ§€ μ•Šκ³  μ΄μ–΄μ„œ μˆœμœ„λ₯Ό λΆ€μ—¬ν•©λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄ 3μœ„κ°€ 3λͺ…이라면, 1,2,3,3,3,4,5,6, ... μ΄λ ‡κ²Œ μˆœμœ„κ°€ λ§€κ²¨μ§‘λ‹ˆλ‹€.

DENSE_RANK() 문법

MySQLκ³Ό Oracle의 DENSE_RANK() ν•¨μˆ˜ 문법은 각각 μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

MySQL 

DENSE_RANK() OVER (
    PARTITION BY partition_expression
    ORDER BY sort_expression [ASC|DESC]
)

Oracle

DENSE_RANK( ) OVER([ query_partition_clause ] order_by_clause)

 

PARTITION BY | query_partition_clause κ³Ό ORDER BY | order_by_clauseλŠ” RANK() ν•¨μˆ˜μ—μ„œμ˜ μ„€λͺ…κ³Ό κ°™μŠ΅λ‹ˆλ‹€.

DENSE_RANK()λŠ” νŒŒν‹°μ…˜μ— λ™μΌν•œ μˆœμœ„ 값을 κ°€μ§„ 두 개 μ΄μƒμ˜ 행이 μžˆλŠ” 경우, 각 행에 동일 μˆœμœ„κ°€ λΆ€μ—¬λ˜κ³ , RANK()ν•¨μˆ˜μ™€λŠ” 달리 항상 μ—°μ†λœ μˆœμœ„ 값을 ν• λ‹Ή ν•©λ‹ˆλ‹€. (동일 μˆœμœ„κ°€ μžˆλ‹€ν•˜λ”λΌλ„)

 

3. ROW_NUMBER() ν•¨μˆ˜

[MySQL Tutorial]
ROW_NUMBER() ν•¨μˆ˜λŠ” κ²°κ³Ό μ§‘ν•©μ˜ 각 행에 일련 번호λ₯Ό ν• λ‹Ήν•˜λŠ” μœˆλ„μš° ν•¨μˆ˜ ν˜Ήμ€ 뢄석 ν•¨μˆ˜μž…λ‹ˆλ‹€.
첫번째 μˆ«μžλŠ” 1둜 μ‹œμž‘ν•©λ‹ˆλ‹€.


[Oracle Tutorial]
ROW_NUMBER() ν•¨μˆ˜λŠ” μ μš©λ˜λŠ” 각 ν–‰(νŒŒν‹°μ…˜μ˜ 각 ν–‰ λ˜λŠ” κ²°κ³Ό μ§‘ν•©μ˜ 각 ν–‰)에 순차적으둜 κ³ μœ ν•œ μ •μˆ˜λ₯Ό ν• λ‹Ήν•˜λŠ” 뢄석 ν•¨μˆ˜μž…λ‹ˆλ‹€.

 

ROW_NUMBER() ν•¨μˆ˜λŠ” κ²°κ³Ό μ§‘ν•© λ‚΄μ˜ 각 행에 고유 번호λ₯Ό ν• λ‹Ήν•©λ‹ˆλ‹€.

RANK()λ‚˜ DENSE_RANK() ν•¨μˆ˜λ³΄λ‹€ 맀우 κ°„λ‹¨ν•©λ‹ˆλ‹€.

ROW_NUMBER() ν•¨μˆ˜λŠ” 각 행에 μˆœμœ„λ₯Ό λΆ€μ—¬ν•  λ•Œ λ™μΌν•œ 값이 μžˆμ–΄λ„ 이λ₯Ό λ¬΄μ‹œν•˜κ³  연속적인 μˆœμœ„λ₯Ό λΆ€μ—¬ν•©λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄ 3μœ„κ°€ 3λͺ…이라해도, 1,2,3,4,5,6, ... μ΄λ ‡κ²Œ μˆœμœ„κ°€ λ§€κ²¨μ§‘λ‹ˆλ‹€.

 

ROW_NUMBER() 문법

MySQLκ³Ό Oracle의 RANK() ν•¨μˆ˜ 문법은 각각 μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

MySQL 

ROW_NUMBER() OVER (
    PARTITION BY <expression>,[{,<expression>}...]
    ORDER BY <expression> [ASC|DESC],[{,<expression>}...]
)

Oracle

ROW_NUMBER() OVER (
   [query_partition_clause] 
   order_by_clause
)

PARTITION BY | query_partition_clause κ³Ό ORDER BY | order_by_clauseλŠ” RANK() ν•¨μˆ˜μ—μ„œμ˜ μ„€λͺ…κ³Ό κ°™μŠ΅λ‹ˆλ‹€.

 

4. RANK() vs DENSE_RANK() vs ROW_NUMBER()

μ§€κΈˆκΉŒμ§€ μ•Œμ•„λ³Έ 3κ°€μ§€ μœˆλ„μš° ν•¨μˆ˜μΈ RANK(), DENSE_RANK(), ROW_NUMBER()의 μ‹€μ œ κ²°κ³Όκ°’μ˜ 차이λ₯Ό ν™•μΈν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

 

학생 정보가 λ‹΄κΈ΄ ν…Œμ΄λΈ”μ„ κ°„λ‹¨ν•˜κ²Œ λ§Œλ“€κ³ , 학생별 ν‰μ μœΌλ‘œ 각 μˆœμœ„ ν•¨μˆ˜μ˜ 차이λ₯Ό ν™•μΈν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

CREATE TABLE `students` (
  `student_id` int NOT NULL,
  `first_name` varchar(50) DEFAULT NULL,
  `last_name` varchar(50) DEFAULT NULL,
  `major` varchar(100) DEFAULT NULL,
  `gpa` decimal(3,2) DEFAULT NULL, // 평점
  PRIMARY KEY (`student_id`)
)

μ λ‹Ήν•œ 데이터λ₯Ό μ—¬λŸ¬κ°œ INSERT ν•œ ν›„ μ•„λž˜ 쿼리λ₯Ό μ‹€ν–‰μ‹œμΌœ λ³΄κ² μŠ΅λ‹ˆλ‹€.

SELECT student_id , first_name , gpa 
		, RANK() OVER (ORDER BY gpa DESC) AS 'RANK'
		, DENSE_RANK () OVER (ORDER BY gpa DESC) AS 'DENSE_RANK'
		, ROW_NUMBER() OVER (ORDER BY gpa DESC, first_name ASC) AS 'ROW_NUM'
FROM students;

μ‹€ν–‰μ‹œν‚¨ κ²°κ³ΌλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

student_id first_name gpa RANK DENSE_ RANK ROW_NUM
3 예린 3.95 1 1 1
2 λ―Όμ§€ 3.90 2 2 2
8 μ§€μš° 3.90 2 2 3
6 μ†Œλ―Ό 3.85 4 3 4
4 μ§€ν˜„ 3.85 4 3 5
5 λ―Όμ€€ 3.80 6 4 6
10 영희 3.80 6 4 7
9 μŠΉν˜„ 3.75 8 5 8
7 μ€€ν˜Έ 3.75 8 5 9
1 민수 3.7 10 6 10

 

3,4번 행을 보면, 3번 ν–‰μ˜ μ§€μš°μ™€ 4번 ν–‰μ˜ μ†Œλ―Όμ΄μ˜ μˆœμœ„ 값이 각 ν•¨μˆ˜λ³„λ‘œ λ‹€λ₯Έ 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

그리고 각 ν•¨μˆ˜λ³„λ‘œ μˆœμœ„λ„ λ‹€λ₯΄κ²Œ λ§€κ²¨μ§€λŠ” 것을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

  • RANK: 1 β­’ 2 β­’ 4 β­’ 6 β­’ 8 β­’ 10
  • DENSE_RANK: 1 β­’ 2 β­’ 3 β­’ 4 β­’ 5 β­’ 6
  • ROW_NUM: 1 β­’ 2 β­’ 3 β­’ 4 β­’ 5 β­’ 6 β­’ 7 β­’ 8 β­’ 9 β­’ 10

 

5. PARTITION BY  문법

μΆ”κ°€λ‘œ μ„Έκ°€μ§€ ν•¨μˆ˜μ—μ„œ λͺ¨λ‘ μ˜΅μ…˜ κ°’μœΌλ‘œ μ‚¬μš©λ˜λŠ” νŒŒν‹°μ…˜ ꡬ문에 λŒ€ν•œ μ‚¬μš©λ²•μ„ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

PARTITION BYλŠ” κ·Έλ£Ή λ‚΄ μˆœμœ„ 및 그룹별 집계λ₯Ό ꡬ할 λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.

SELECT student_id , major , gpa 
	,RANK() OVER (PARTITION BY major ORDER BY gpa DESC) AS 'PARTITION'
FROM STUDENTS;

 

이 μΏΌλ¦¬λŠ” ν•™μƒλ“€μ˜ 전곡(major)λ³„λ‘œ ν•™μƒλ“€μ˜ 평점(gpa)μˆœμœ„λ₯Ό λ§€κΉλ‹ˆλ‹€.

  • PARTITION BY major ORDER BY gpa DESC: major 컬럼이 같은 행을 그룹으둜 λ¬Άμ–΄μ„œ, κ·Έλ£Ή λ‚΄ gpa 컬럼의 μˆœμœ„λ₯Ό λ‚΄λ¦Όμ°¨μˆœ(DESC)으둜 μ •λ ¬

μœ„ 쿼리λ₯Ό μ‹€ν–‰ν•œ κ²°κ³ΌλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

student_id major gpa PARTITION
1 κ²½μ˜ν•™ 3.6 1
8 κ²½μ˜ν•™ 3.5 2
7 κ²½μ˜ν•™ 3.45 3
4 κ²½μ˜ν•™ 3.4 4
9 생물학 3.2 1
6 생물학 3.05 2
3 심리학 3.85 1
5 심리학 3.85 1
2 심리학 3.75 3
10 심리학 3.55 4

 


마치며,

μœˆλ„μš° ν•¨μˆ˜ 쀑 ν•˜λ‚˜μΈ μˆœμœ„ ν•¨μˆ˜μ— λŒ€ν•΄ μ•Œμ•„λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

μ½”λ”©ν…ŒμŠ€νŠΈλ₯Ό ν•˜λ©΄μ„œ RANK() ν•¨μˆ˜λ₯Ό ν™œμš©ν•΄μ•Όν•˜λŠ” 쿼리λ₯Ό μ œλŒ€λ‘œ μž‘μ„±ν•˜μ§€ λͺ»ν•΄ λ‹€μ‹œ κ³΅λΆ€ν•˜λ©΄μ„œ μ •λ¦¬ν•˜λ‹ˆ 전에 κ³΅λΆ€ν–ˆλ˜ λ‚΄μš©μ΄ λ‹€μ‹œ μƒκ°λ‚˜κΈ°λ„ ν•˜κ³  μƒˆλ‘­κ²Œ λ‹€μ‹œ λ°°μš°κΈ°λ„ ν–ˆμŠ΅λ‹ˆλ‹€.

κ΄€λ ¨ν•œ λ‹€λ₯Έ ν•¨μˆ˜λ“€λ„ 많이 μžˆμœΌλ‹ˆ, λ‹€μŒμ—λŠ” 이외 ν•¨μˆ˜λ“€λ„ μ •λ¦¬ν•˜λŠ” μ‹œκ°„μ„ κ°€μ Έλ³΄μ•„μ•Όκ² μŠ΅λ‹ˆλ‹€ :)

 

참고 링크

 

A Guide to MySQL RANK Funtion By Practical Examples

This tutorial introduces to the MySQL RANK function and how to apply it to assign the rank to each row within the partition of a result set.

www.mysqltutorial.org

 

Oracle RANK() Function By Practical Examples

In this tutorial, you will learn how to use Oracle RANK() function to calculate the rank of rows within a set of rows.

www.oracletutorial.com

+ Recent posts