1. 문제 설명 📌
(1) 링크🔗
(2) 해설🕵
KEY WORD
: 문자열 자르기
, 집계 함수
해당 문제는 "'YYYY/MM/DD' 형식의 TIME에서 앞 4자리의 연도를 짜를 수 있는가?"를 묻는 문제이다.
2. 구현 코드 🔎
A. DATE 문 전용 함수 사용
SELECT COUNT(*) AS FISH_COUNT
FROM FISH_INFO
WHERE YEAR(time) = 2021;
B. DATE TYPE이 아닌 경우도 쓸 수 있는 함수 활용
substr() 활용
select count(*) as FISH_COUNT
from FISH_INFO
where substr(time, 1, 4) = '2021';
Like 활용
select count(*) as FISH_COUNT
from FISH_INFO
where TIME LIKE '2021%'
해당 문제는 시간을 나타내는 TIME 열이 DATE
TYPE 이기 떄문에 DATE Function을 쓸 수 있었다. 만약 단순 VAR CHAR문이면 subStr()이나 Like문을 쓰는 것도 좋은 선택이라 생각이 든다.
3. DRILING 🎯
(1) DATE type에 관하여
A. DATE type의 종류
DATE
: 날짜만TIME
: 시간만DATETIME
: 날짜 + 시간TIMESTAMP
: 날짜 + 시간 (지역 시간대 반영)
B. DATE <-> 문자열 형변환에 대하여
DATE 함수를 쓸 때 인수로 문자열을 넣어도 성립함을 종종 볼 수 있다. (ex- YEAR('2025-05-20')) 이러한 쿼리문 실현에서 알 수 있듯이 DATE와 VAR CHAR 간에는 묵시적 형변환이 이루어진다. 내부 SQL 옵티마이저는 YEAR('2025-05-20')의 함수가 들어오면 내부에서 CAST(char AS date)이라는 형변환 함수를 먼저 돌린 뒤에 함수를 실행한다. (date에서 문자열로 바꾸는 경우도 마찬가지) 하지만 이렇게 묵시적 형변환을 시키려면, 문자열의 형태를 정해진 date 형식으로 적어야 한다.
DATE type을 형 변환이 가능한 VAR CHAR 구문 예시
MySQL에서 표준 DATE의 형식은 yyyy-mm-dd
이다. 어떤 형식으로 쿼리문을 짜든, 테이블 내의 저장 형태는 yyyy-mm-dd
를 쓴다. 다음은 개발자가 개떡같이 입력해도, mySQL의 옵티마이저가 찰떡같이 알아듣는 예시이다.
입력 값 | 결과 | 설명 |
---|---|---|
'2024-04-15' |
2024-04-15 |
기본 형식 |
'20240415' |
2024-04-15 |
숫자형도 허용 |
'24-4-15' |
2024-04-15 |
축약형 (1의 자리 수일 때 앞에 0 빼도 됨.) |
'2024.04.15' |
2024-04-15 |
구분자 변경도 자동 인식 |
'2024/04/15' |
2024-04-15 |
슬래시도 허용 |
(2) DATE 전용 함수 (DATE Function
) 의 정의와 종류
A. 정의
DATE
, DATETIME
, TIMESTAMP
등 날짜/ 시간 데이터에서 원하는 데이터를 추출할 수 있도록 도와주는 함수들을 DATE Function 이라 부른다.
B. DATE 함수의 종류
함수 | 설명 | 예시 | 결과 |
---|---|---|---|
YEAR(date) | 연도 추출 | YEAR('2025-05-20') | 2025 |
MONTH(date) | 월 추출 | MONTH('2025-05-20') | 5 |
DAY(date) 혹은 DAYOFMONTH(date) | 일 추출 | DAY('2025-05-20') | 20 |
DATE(dateTime) | 날짜만 추출(DATETIME -> DATE ) |
DATE('2025-05-20 12:30:00') | 2025-05-20 |
TIME(dateTime) | 시간만 추출 (DATETIME -> TIME ) |
TIME('2025-05-20 12:30:00') | 12:30:00 |
HOUR(dateTime) | 시간 중 시 만 추출 |
HOUR('2025-05-20 12:30:00') | 12 |
MINUTE(date) | 분 추출 | MINUTE('2025-05-20 12:30:00') | 30 |
SECOND(date) | 초 추출 | SECOND('2025-05-20 12:30:00') | 0 |
DATE_FORMAT(date, format) | 원하는 형식으로 변환 | DATE_FORMAT('2025-05-20', '%Y-%M') | '2025-05' |
DATE_FORMAT에서 와일드 카드 구문의 종류
DATE를 원하는 형식의 문자열로 바꿀 떄, 원하는 형식을 와일드 카드로 미리 정할 수 있다.
형식 | 의미 | 예시 (2024-04-15 13:45:00 ) |
---|---|---|
%Y |
연도 (4자리) | 2024 |
%y |
연도 (2자리) | 24 |
%m |
월 (2자리) | 04 |
%c |
월 (1~12) | 4 |
%d |
일 (2자리) | 15 |
%e |
일 (1~31) | 15 |
%H |
시 (24시간제) | 13 |
%h / %I |
시 (12시간제) | 01 |
%i |
분 | 45 |
%s |
초 | 00 |
(3) 해당 문제에서 문자열 함수 (subStr() 이나 Like)를 쓰면 느린가?
결론
: 느려진다!
위에서 살펴보았듯이 컬럼 자체가 DATE type이면, 바로 DATE 함수를 쓰는 것이 제일 빠르다. 만약 문자열 함수를 쓰면 다음과 같은 이유로 느려진다.
이유
:
- 암묵적 형변환이 이루어짐, 옵티마이저가 내부적으로 CAST(date as char) 함수를 모든 행마다 실행해야함.
- subStr의 경우 해당 부분 문자열만큼 새로운 문자열을 행마다 만든다. ex(substr(1,4, time) -> 모든 time 열의 값에서 앞 4자리만 짤라서 새로운 문자열 생성)
- 이후 함수 연산
이모지 모음: 🤔, ➜ ✨ 0️⃣1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣8️⃣9️⃣🔟