λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ ν•„μˆ˜λ‘œ μ“°μ΄λŠ” λ‚ μ§œν˜• 데이터에 λŒ€ν•΄ μ •λ¦¬ν•΄λ‘κ³ μž ν•©λ‹ˆλ‹€.

4κ°€μ§€ μœ ν˜•μ˜ 데이터 νƒ€μž…μ— λŒ€ν•œ 정리와 μΌμžμ™€ μ‹œκ°„μ„ λͺ¨λ‘ ν‘œν˜„ν•˜λŠ” DATETIMEκ³Ό TIMESTAMP의 차이λ₯Ό μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

1. DATE, DATETIME, TIMESTAMP, TIME

MySQLμ—μ„œλŠ” μΌμžμ™€ μ‹œκ°„μ„ ν‘œν˜„ν•˜κΈ°μœ„ν•΄ DATE, DATETIME, TIMESTAMP, TIME νƒ€μž…μ„ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  DATE DATETIME TIMESTAMP TIME
상세 일자만 ν‘œν˜„ - μΌμžμ™€ μ‹œκ°„ ν‘œν˜„
- μ΅œλŒ€ λ§ˆμ΄ν¬λ‘œμ΄ˆ μ •λ°€λ„μ˜ μ†Œμˆ˜ μ΄ˆλ₯Ό ν¬ν•¨ κ°€λŠ₯
- ν˜„μž¬ λ‚ μ§œμ™€ μ‹œκ°„μœΌλ‘œ μžλ™ μ΄ˆκΈ°ν™” λ° μ—…λ°μ΄νŠΈκ°€ κ°€λŠ₯
- μΌμžμ™€ μ‹œκ°„ ν‘œν˜„
- (default) NOT NULL
- Timezone 기반
- μ΅œλŒ€ λ§ˆμ΄ν¬λ‘œμ΄ˆ μ •λ°€λ„μ˜ μ†Œμˆ˜ μ΄ˆλ₯Ό ν¬ν•¨ κ°€λŠ₯
- ν˜„μž¬ λ‚ μ§œμ™€ μ‹œκ°„μœΌλ‘œ μžλ™ μ΄ˆκΈ°ν™” λ° μ—…λ°μ΄νŠΈκ°€ κ°€λŠ₯
μ‹œκ°„λ§Œ ν‘œν˜„
ν˜•μ‹ YYYY-MM-DD YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss hh:mm:ss
λ²”μœ„ '1000-01-01'
~'9999-12-31'
'1000-01-01 00:00:00'
~ '9999-12-31 23:59:59'
'1970-01-01 00:00:01' UTC
~ '2038-01-19 03:14:07' UTC
'-838:59:59' ~'838:59:59' 
μš©λŸ‰ 3byte 8byte 4byte 3byte

 

μΌμžμ™€ μ‹œκ°„μ„ λͺ¨λ‘ ν‘œν˜„ν•˜λŠ” DATETIMEκ³Ό TIMESTAMPλŠ” μ–Όν•λ΄μ„œλŠ” λΉ„μŠ·ν•œλ°, 차이점이 μžˆμŠ΅λ‹ˆλ‹€. 

이 λ‘˜μ˜ 차이λ₯Ό μ•Œκ³  μžˆμ–΄μ•Ό μ˜ˆμƒμΉ˜ λͺ»ν•œ μ—λŸ¬μ‚¬ν•­μ„ λŒ€λΉ„ν•  수 있기 λ•Œλ¬Έμ—, 차이점을 ν•œ 번 μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

2. DATETIME vs TIMESTAMP

1) λ²”μœ„

μΌμžμ™€ μ‹œκ°„μ„ λͺ¨λ‘ ν‘œν˜„ν•˜λŠ” 두 νƒ€μž…μ€ 일단 ν‘œμ—μ„œ λ³Ό 수 μžˆλ“― λ²”μœ„μ—μ„œ 차이가 μžˆμŠ΅λ‹ˆλ‹€.

DATETIME의 λ²”μœ„λŠ” '1000-01-01 00:00:00' λΆ€ν„° '9999-12-31 23:59:59' 둜, μ‹œκ°„λŒ€μ— 관계없이 μ ˆλŒ€μ μΈ μΌμžμ™€ μ‹œκ°„μ„ μ €μž₯ν•©λ‹ˆλ‹€.

TIMESTAMP의 λ²”μœ„λŠ” '1970-01-01 00:00:01' UTC λΆ€ν„° '2038-01-19 03:14:07' UTC 둜, 데이터가 UTC둜 λ³€ν™˜λ˜μ–΄ μ €μž₯되며 κ²€μƒ‰μ‹œ ν˜„μž¬ μ‹œκ°„λŒ€λ‘œ λ³€ν™˜μ΄ λ©λ‹ˆλ‹€. TIMESTAMP의 λ²”μœ„λŠ” Unix μ‹œκ°„κ³Ό 관련이 μžˆμ–΄, 2038λ…„ 문제둜 인해 μ΅œλŒ€ λ²”μœ„κ°€ 2038λ…„κΉŒμ§€λ‘œ μ œν•œλ©λ‹ˆλ‹€.

2) Timezone의 적용 μ—¬λΆ€

두 νƒ€μž…μ€ Timezone의 적용 여뢀에 차이가 μžˆμŠ΅λ‹ˆλ‹€.

Timezone은 λ™μΌν•œ μ‹œκ°„μ„ λ”°λ₯΄λŠ” 지역을 μ˜λ―Έν•˜κ³ , ν•΄λ‹Ή ꡭ가에 μ˜ν•΄ λ²•μ μœΌλ‘œ μ§€μ •λ˜λŠ” κ°’μž…λ‹ˆλ‹€.

UTC, Asia/Seoul λ“±μ˜ ν‘œκΈ°κ°€ ν•΄λ‹Ή μ‹œκ°„μ΄ μ–΄λ–€ λ‘œμ»¬μ„ κΈ°μ€€μœΌλ‘œ μž‘μ„±ν•œ 것인지λ₯Ό λͺ…μ‹œν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

 

MySQL은 TIMESTAMP 값을 ν˜„μž¬ μ‹œκ°„λŒ€μ—μ„œ *UTC둜 λ³€ν™”ν•˜μ—¬ μ €μž₯ν•˜κ³ , λ‹€μ‹œ UTCμ—μ„œ ν˜„μž¬ μ‹œκ°„λŒ€λ‘œ λ³€ν™˜ν•˜μ—¬ κ²€μƒ‰ν•©λ‹ˆλ‹€.

*UTC: ꡭ제 ν‘œμ€€μ‹œ

기본적으둜 μ„€μ •λ˜λŠ” μ‹œκ°„λŒ€λŠ” μ„œλ²„ μ‹œκ°„μœΌλ‘œ, μ‹œκ°„λŒ€ 섀정이 μΌμ •ν•˜κ²Œ μœ μ§€λœλ‹€λ©΄ μ €μž₯ν•œ κ°’κ³Ό λ™μΌν•œ 값을 λ°˜ν™˜λ°›μŠ΅λ‹ˆλ‹€.

λ§Œμ•½ TIMESTAMP 값을 μ €μž₯ν•œ ν›„, μ‹œκ°„λŒ€λ₯Ό λ³€κ²½ν•˜κ³  값을 μ‘°νšŒν•˜λ©΄, 쑰회 κ²°κ³ΌλŠ” μ €μž₯ν•œ κ°’κ³Ό λ‹€λ₯΄κ²Œ λ©λ‹ˆλ‹€. μ‹œκ°„λŒ€ λ³€ν™˜μ‹œ λ™μΌν•œ μ‹œκ°„λŒ€λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— μ΄λŸ¬ν•œ κ²°κ³Όκ°€ λ°œμƒν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

*ν˜„ μ‹œκ°„λŒ€λŠ” μ‹œμŠ€ν…œ λ³€μˆ˜μΈ time_zone 에 μ„€μ •λœ κ°’μœΌλ‘œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

μ˜ˆμ‹œ

μ‹€μ œλ‘œ 데이터가 μ–΄λ–»κ²Œ μ €μž₯λ˜λŠ”μ§€ ν™•μΈν•΄λ΄…μ‹œλ‹€.

create table date_example
(
  test_date date,
  test_datetime datetime,
  test_timestamp timestamp,
  test_time time
);

insert into date_example values (now(), now(), now(), now());

ν…ŒμŠ€νŠΈ ν…Œμ΄λΈ”μ„ λ§Œλ“€κ³  ν˜„μž¬ μ‹œκ°„μœΌλ‘œ 데이터λ₯Ό μ €μž₯ν–ˆμŠ΅λ‹ˆλ‹€.

mysql> select * from date_example;
+------------+---------------------+---------------------+-----------+
| test_date  | test_datetime       | test_timestamp      | test_time |
+------------+---------------------+---------------------+-----------+
| 2024-07-09 | 2024-07-09 10:36:17 | 2024-07-09 10:36:17 | 10:36:17  |
+------------+---------------------+---------------------+-----------+
1 row in set (0.00 sec)

μ™Όμͺ½λΆ€ν„° DATE, DATETIME, TIMESTAMP, TIME ν˜•μ‹μ˜ 데이터가 μ €μž₯된 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

μ—¬κΈ°μ„œ time_zone을 μˆ˜μ •ν•΄λ³΄κ³  λ‹€μ‹œ 같은 데이터λ₯Ό ν™•μΈν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

mysql> SET time_zone = '+01:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select * from date_example;
+------------+---------------------+---------------------+-----------+
| test_date  | test_datetime       | test_timestamp      | test_time |
+------------+---------------------+---------------------+-----------+
| 2024-07-09 | 2024-07-09 10:36:17 | 2024-07-09 02:36:17 | 10:36:17  |
+------------+---------------------+---------------------+-----------+
1 row in set (0.00 sec)

time_zone에 λ³€ν™”λ₯Ό μ£Όκ³  μ‘°νšŒν•΄λ³΄λ‹ˆ TIMESTAMP ν˜•μ‹μ˜ test_timstamp κ°’λ§Œ λ³€ν•œ 것을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

  • SET time_zone = '+01:00' : UTC+09:00 보닀 8μ‹œκ°„ μ΄μ „μœΌλ‘œ μ„€μ •

μ΄λŠ” μœ„μ—μ„œ κΈ°μž¬ν–ˆλ“― TIMESTAMP λŠ” μ‹œμŠ€ν…œ λ³€μˆ˜μΈ time_zone을 κΈ°μ€€μœΌλ‘œ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

κ·Έλ ‡κΈ°λ•Œλ¬Έμ— TIMESTAMPλ₯Ό μ‚¬μš©ν•˜κ³ , 둜컬 μ‹œκ°„μ΄ λ‹€λ₯Έ κΈ€λ‘œλ²Œ μ„œλΉ„μŠ€λ₯Ό μš΄μ˜ν•  λ•Œμ—λŠ” 이λ₯Ό μœ μ˜ν•΄μ„œ κ΄€λ¦¬ν•΄μ•Όν•©λ‹ˆλ‹€.

 

TIMESTAMPλ₯Ό μ‚¬μš©ν•˜λ©΄ 둜컬 μ‹œκ°„μ— 따라 ν˜Όλž€μ΄ μžˆμ„ μˆ˜λŠ” μžˆμœΌλ‚˜, κΈ€λ‘œλ²Œ μ„œλΉ„μŠ€λ₯Ό μš΄μ˜ν• λ•Œμ—λŠ” μœ μš©ν•˜κ²Œ 쓰일 수 μžˆμŠ΅λ‹ˆλ‹€.

λ§Œμ•½ DATETIME을 μ‚¬μš©ν•œλ‹€λ©΄ 둜컬 μ‹œκ°„μ΄ μ œλŒ€λ‘œ λ°˜μ˜λ˜μ§€ μ•Šμ•„μ„œ, μ„œμšΈμ—μ„œ μ˜€μ „ 11μ‹œμ— μž‘μ„±ν•œ 글을 λ―Έκ΅­μ—μ„œ μ‘°νšŒν•˜λŠ” 경우, λ™μΌν•˜κ²Œ μ˜€μ „ 11μ‹œλ‘œ λ°˜μ˜λ˜λŠ” λ“±μ˜ λ¬Έμ œκ°€ λ°œμƒν•©λ‹ˆλ‹€. μ΄λ ‡κ²Œ μ‹œκ°„μ΄ λ‹€λ₯Έ 지역이 μžˆλŠ” 경우, TIMESTAMPκ°€ 더 적합할 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

 

μ΄λŸ¬ν•œ νŠΉμ§•λ“€λ‘œ DATETIME은 μ ˆλŒ€μ μΈ μ‹œκ°„ 기둝에 μ ν•©ν•˜κ³  TIMESTAMPλŠ” μ‹œκ°„λŒ€μ— 따라 λ³€ν™˜μ΄ ν•„μš”ν•œ 경우 μœ μš©ν•˜κ²Œ μ“°μž…λ‹ˆλ‹€.

3) DATETIME κ³Ό TIMESTAMP의 μžλ™ μ΄ˆκΈ°ν™”

DATETIME와 TIMESTAMPλŠ” ν˜„μž¬ μΌμžμ™€ μ‹œκ°„μ„ κΈ°λ³Έκ°’, μžλ™ μ—…λ°μ΄νŠΈ κ°’μœΌλ‘œ μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • μžλ™ μ΄ˆκΈ°ν™”: 데이터 μ‚½μž…μ‹œ λͺ…μ‹œμ μœΌλ‘œ μ§€μ •ν•˜μ§€ μ•Šμ•„λ„ ν˜„μž¬ νƒ€μž„μŠ€νƒ¬ν”„λ‘œ μ„€μ •
  • μžλ™ μ—…λ°μ΄νŠΈ: 데이터 κ°±μ‹ μ‹œ μžλ™μœΌλ‘œ ν˜„μž¬ νƒ€μž„ μŠ€νƒ¬ν”„λ‘œ κ°±μ‹ 

μ„€μ • 방법

μžλ™ μ΄ˆκΈ°ν™”μ™€ μ—…λ°μ΄νŠΈλ₯Ό μ„€μ •ν•˜λ €λ©΄ DATETIMEκ³Ό TIMESTAMP μ—΄ μ •μ˜μ—μ„œ μ§€μ •ν•΄μ£Όλ©΄ λ©λ‹ˆλ‹€.

  • μžλ™ μ΄ˆκΈ°ν™”λ₯Ό μœ„ν•œ μ΄ˆκΈ°κ°’ μ„€μ •: DEFAULT ~~
  • μžλ™ μ—…λ°μ΄νŠΈλ₯Ό μœ„ν•œ μ„€μ •: ON UPDATE ~~

DATETIMEκ³Ό TIMESTAMPλ₯Ό 각각 ν˜•μ‹μœΌλ‘œ κ°€μ§€λŠ” column이 μžˆλŠ” ν…Œμ΄λΈ”μ„ μ•„λž˜μ™€ 같이 μ •μ˜ν•˜λ©΄ μžλ™μœΌλ‘œ 값이 λ“€μ–΄κ°‘λ‹ˆλ‹€.

CREATE TABLE t1 (
  ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

μœ„ ν…Œμ΄λΈ”μ— 아무 값도 μ§€μ •ν•˜μ§€ μ•Šκ³  INSERTλ₯Ό ν•˜κ³  쑰회λ₯Ό ν•˜λ©΄, 

insert into t1 values();

아무 값도 λ„£μ§€ μ•Šμ•˜λŠ”λ°λ„ ν˜„μž¬ μ‹œκ°„μ΄ μ €μž₯된 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

mysql> select * from t1;
+---------------------+---------------------+
| ts                  | dt                  |
+---------------------+---------------------+
| 2024-07-09 12:13:49 | 2024-07-09 12:13:49 |
+---------------------+---------------------+
1 row in set (0.00 sec)

 

μ΄λ²ˆμ—” μ•„λž˜μ™€ 같은 ν…Œμ΄λΈ”μ„ μƒμ„±ν•΄λ΄…μ‹œλ‹€.

CREATE TABLE t1 (
  ts TIMESTAMP DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  dt DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
);

μœ„μ—μ„œ μ •μ˜ν•œ 것과 λ‹€λ₯Έμ μ€ DEFAULT NULL λΆ€λΆ„μž…λ‹ˆλ‹€.

μ΄λŠ” 기본값을 NULL둜 λ‘κ² λ‹€λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.

 

mysql> INSERT INTO t1 VALUES();
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM T1;
+------+------+
| ts   | dt   |
+------+------+
| NULL | NULL |
+------+------+
1 row in set (0.00 sec)

μœ„μ™€ λ™μΌν•˜κ²Œ 아무 값도 λ„£μ§€ μ•Šκ³  INSERTλ₯Ό ν•˜λ©΄, μ΄λ²ˆμ—λŠ” NULL 값이 μ €μž₯된 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.


마치며,

μ„œλΉ„μŠ€λ₯Ό μš΄μ˜ν•˜λ©΄ ν•„μˆ˜μ μœΌλ‘œ ν¬ν•¨λ˜λŠ” λ‚ μ§œμ™€ μ‹œκ°„ λ°μ΄ν„°ν˜•μ— λŒ€ν•œ λ‚΄μš©μ„ μ •λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.

특히 DATETIMEκ³Ό TIMESTAMP의 μ°¨μ΄μ—μ„œ ν—·κ°ˆλ¦¬λŠ” 뢀뢄이 λ§Žμ•˜λŠ”λ°, μ΄λ²ˆμ— μ •λ¦¬ν•˜κ³  μ°Ύμ•„λ³΄λ©΄μ„œ ν•œλ²ˆ 더 확인할 수 μžˆμ—ˆλ˜ μ‹œκ°„μ΄μ—ˆμŠ΅λ‹ˆλ‹€. λ‚ μ§œ 데이터와 κ΄€λ ¨ν•΄μ„œλŠ” λ‹€μŒμ— λ¬Έμžμ—΄λ‘œ λ³€ν™˜ν•˜λŠ” λ“± μ‹€μ œλ‘œ 값을 μ‘°νšŒν•˜κ³  μ²˜λ¦¬ν•˜λŠ” 뢀뢄에 λŒ€ν•΄μ„œ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

 

Reference

 

MySQL :: MySQL 8.4 Reference Manual :: 13.2.2 The DATE, DATETIME, and TIMESTAMP Types

13.2.2 The DATE, DATETIME, and TIMESTAMP Types The DATE, DATETIME, and TIMESTAMP types are related. This section describes their characteristics, how they are similar, and how they differ. MySQL recognizes DATE, DATETIME, and TIMESTAMP values in several f

dev.mysql.com

 

MySQL :: MySQL 8.4 Reference Manual :: 13.2.5 Automatic Initialization and Updating for TIMESTAMP and DATETIME

13.2.5 Automatic Initialization and Updating for TIMESTAMP and DATETIME TIMESTAMP and DATETIME columns can be automatically initialized and updated to the current date and time (that is, the current timestamp). For any TIMESTAMP or DATETIME column in a ta

dev.mysql.com

'πŸ’» Programming > SQL' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[SQL] μˆœμœ„ ν•¨μˆ˜(MySQL, Oracle)  (0) 2024.07.08

πŸ“Œμš”μ•½

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

  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