1. MySQL 기본 날짜 함수
MySQL에서 날짜와 시간을 다루는 기본 함수들부터 알아봅시다.
현재 날짜 및 시간 구하기
-- 현재 날짜만 가져오기
SELECT CURDATE(); -- 2025-03-19
-- 다른 형식으로 현재 날짜 가져오기
SELECT CURRENT_DATE(); -- 2025-03-19
-- 현재 시간만 가져오기
SELECT CURTIME(); -- 14:30:25
-- 현재 날짜와 시간 가져오기
SELECT NOW(); -- 2025-03-19 14:30:25
-- 다른 형식으로 현재 날짜와 시간 가져오기
SELECT CURRENT_TIMESTAMP(); -- 2025-03-19 14:30:25
활용 팁: NOW()는 쿼리 실행 시점의 시간을 반환하지만, SYSDATE()는 함수가 실행되는 정확한 시점의 시간을 반환합니다. 대부분의 경우 NOW()를 사용하는 것이 좋습니다.
NOW()와 SYSDATE() 차이
-- 동일한 쿼리에서 비교
SELECT NOW(), SLEEP(2), NOW(); -- 모든 NOW() 값이 동일함
SELECT SYSDATE(), SLEEP(2), SYSDATE(); -- SLEEP 이후의 SYSDATE() 값이 2초 차이남
언제 사용할까? 일반적으로 NOW()를 사용하는 것이 안전합니다. 로그 기록이나 정확한 시간 측정이 필요한 경우에만 SYSDATE()를 사용하시길 추천합니다.
2. MySQL 날짜 추출 및 변환
날짜 구성 요소 추출하기
-- 현재 날짜로부터 연, 월, 일 추출
SELECT
YEAR(NOW()) AS '연도', -- 2025
MONTH(NOW()) AS '월', -- 3
DAY(NOW()) AS '일', -- 19
HOUR(NOW()) AS '시', -- 14
MINUTE(NOW()) AS '분', -- 30
SECOND(NOW()) AS '초'; -- 25
실무 활용: 데이터 그룹화나 필터링 시 자주 사용됩니다. 월별 통계 계산, 특정 연도의 데이터만 추출할 때 유용합니다.
날짜 부분 추출 함수 (EXTRACT)
-- EXTRACT 함수로 날짜 부분 추출
SELECT
EXTRACT(YEAR FROM NOW()) AS '연도', -- 2025
EXTRACT(MONTH FROM NOW()) AS '월', -- 3
EXTRACT(DAY FROM NOW()) AS '일', -- 19
EXTRACT(HOUR FROM NOW()) AS '시', -- 14
EXTRACT(MINUTE FROM NOW()) AS '분', -- 30
EXTRACT(SECOND FROM NOW()) AS '초', -- 25
EXTRACT(YEAR_MONTH FROM NOW()) AS '연월', -- 202503
EXTRACT(DAY_HOUR FROM NOW()) AS '일시', -- 1914
EXTRACT(HOUR_MINUTE FROM NOW()) AS '시분', -- 1430
EXTRACT(MINUTE_SECOND FROM NOW()) AS '분초'; -- 3025
특별 기능: MySQL의 EXTRACT 함수는 연월(YEAR_MONTH), 일시(DAY_HOUR) 등 복합 단위 추출도 지원합니다.
요일 및 주차 정보 추출
-- 요일 정보 가져오기
SELECT
DAYNAME(NOW()) AS '요일이름', -- Wednesday
DAYOFWEEK(NOW()) AS '요일숫자1', -- 4 (일요일=1, 수요일=4)
WEEKDAY(NOW()) AS '요일숫자2'; -- 2 (월요일=0, 수요일=2)
-- 주차 및 연중 일수 정보
SELECT
WEEK(NOW()) AS '연중주차', -- 12
WEEK(NOW(), 1) AS '월요일시작주차', -- 12
DAYOFYEAR(NOW()) AS '연중일수', -- 78
QUARTER(NOW()) AS '분기'; -- 1
DAYOFWEEK vs WEEKDAY: DAYOFWEEK는 일요일을 1로, WEEKDAY는 월요일을 0으로 시작합니다. 주간 보고서 생성 시 유의할 필요가 있습니다.
문자열을 날짜로 변환하기
-- 문자열을 날짜로 변환
SELECT STR_TO_DATE('2025-03-19', '%Y-%m-%d'); -- 2025-03-19
-- 다양한 형식의 문자열을 날짜로 변환
SELECT
STR_TO_DATE('19/03/2025', '%d/%m/%Y') AS '영국식날짜', -- 2025-03-19
STR_TO_DATE('03/19/2025', '%m/%d/%Y') AS '미국식날짜', -- 2025-03-19
STR_TO_DATE('2025년 3월 19일', '%Y년 %c월 %e일') AS '한글날짜'; -- 2025-03-19
활용 사례: 사용자 입력이나 CSV 파일 등에서 가져온 문자열 데이터를 MySQL의 DATE/DATETIME 타입으로 변환할 때 사용 가능합니다.
3. MySQL 날짜 연산
날짜 더하기/빼기 (DATE_ADD/DATE_SUB)
-- DATE_ADD 사용
SELECT
NOW() AS '현재', -- 2025-03-19 14:30:25
DATE_ADD(NOW(), INTERVAL 1 DAY) AS '내일', -- 2025-03-20 14:30:25
DATE_ADD(NOW(), INTERVAL -1 DAY) AS '어제', -- 2025-03-18 14:30:25
DATE_ADD(NOW(), INTERVAL 1 MONTH) AS '한달후', -- 2025-04-19 14:30:25
DATE_ADD(NOW(), INTERVAL 1 YEAR) AS '일년후'; -- 2026-03-19 14:30:25
-- DATE_SUB 사용
SELECT
NOW() AS '현재', -- 2025-03-19 14:30:25
DATE_SUB(NOW(), INTERVAL 1 DAY) AS '어제', -- 2025-03-18 14:30:25
DATE_SUB(NOW(), INTERVAL 1 MONTH) AS '한달전', -- 2025-02-19 14:30:25
DATE_SUB(NOW(), INTERVAL 1 YEAR) AS '일년전'; -- 2024-03-19 14:30:25
실무 활용: 만료일 계산(30일 후), 결제 예정일(다음 달), 프로모션 기간(7일 후까지) 등 다양한 업무에 활용될 수 있습니다.
날짜 간 차이 계산 (DATEDIFF/TIMEDIFF)
-- 날짜 간의 일수 차이 계산
SELECT DATEDIFF('2025-12-31', NOW()) AS '올해남은일수'; -- 287 (예시)
-- 시간 간의 차이 계산 (시:분:초 형식)
SELECT TIMEDIFF('17:30:00', '09:00:00') AS '근무시간'; -- 08:30:00
-- 두 날짜/시간 간의 차이를 초 단위로 계산
SELECT TIMESTAMPDIFF(SECOND, '2025-03-19 09:00:00', '2025-03-19 17:30:00') AS '근무시간(초)'; -- 30600
-- 다양한 단위로 차이 계산
SELECT
TIMESTAMPDIFF(YEAR, '1990-05-15', NOW()) AS '만나이(년)', -- 34
TIMESTAMPDIFF(MONTH, '1990-05-15', NOW()) AS '월수', -- 418
TIMESTAMPDIFF(DAY, '2025-01-01', NOW()) AS '일수', -- 78
TIMESTAMPDIFF(HOUR, '2025-03-19 09:00:00', NOW()) AS '시간수'; -- 5 (예시)
DATEDIFF vs TIMESTAMPDIFF: DATEDIFF는 일수 차이만 반환하지만, TIMESTAMPDIFF는 다양한 단위(YEAR, MONTH, DAY, HOUR, MINUTE, SECOND)로 차이를 계산할 수 있습니다.
나이 계산하기
-- 생년월일로 정확한 나이 계산
SELECT TIMESTAMPDIFF(YEAR, '1990-05-15', CURDATE()) AS '만나이'; -- 34
-- 생일 지남 여부를 고려한 정확한 나이 계산
SELECT
TIMESTAMPDIFF(YEAR, '1990-05-15', CURDATE()) -
IF(DATE_FORMAT(CURDATE(), '%m%d') < DATE_FORMAT('1990-05-15', '%m%d'), 1, 0)
AS '정확한만나이'; -- 생일 지남 여부에 따라 34 또는 33
한국식 나이: 한국식 나이(세는 나이)는 위 계산결과에 1을 더하면 됩니다.
4. MySQL 날짜 형식 지정
DATE_FORMAT으로 날짜 형식 지정
-- 다양한 날짜 형식
SELECT
DATE_FORMAT(NOW(), '%Y-%m-%d') AS 'ISO형식', -- 2025-03-19
DATE_FORMAT(NOW(), '%d/%m/%Y') AS '영국식', -- 19/03/2025
DATE_FORMAT(NOW(), '%m/%d/%Y') AS '미국식', -- 03/19/2025
DATE_FORMAT(NOW(), '%Y년 %m월 %d일') AS '한글식', -- 2025년 03월 19일
DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s') AS 'ISO날짜시간'; -- 2025-03-19 14:30:25
활용 사례: 리포트, 웹 페이지 출력, CSV 내보내기 등에서 원하는 형식으로 날짜를 표시할 때 사용됩니다.
자주 사용되는 날짜 형식 지정자
-- 날짜 형식 지정자 예제
SELECT
DATE_FORMAT(NOW(), '%Y') AS '4자리연도', -- 2025
DATE_FORMAT(NOW(), '%y') AS '2자리연도', -- 25
DATE_FORMAT(NOW(), '%m') AS '월(숫자-0포함)', -- 03
DATE_FORMAT(NOW(), '%c') AS '월(숫자-0제외)', -- 3
DATE_FORMAT(NOW(), '%M') AS '월(영문-전체)', -- March
DATE_FORMAT(NOW(), '%b') AS '월(영문-약자)', -- Mar
DATE_FORMAT(NOW(), '%d') AS '일(0포함)', -- 19
DATE_FORMAT(NOW(), '%e') AS '일(0제외)', -- 19
DATE_FORMAT(NOW(), '%W') AS '요일(전체)', -- Wednesday
DATE_FORMAT(NOW(), '%a') AS '요일(약자)'; -- Wed
-- 시간 형식 지정자 예제
SELECT
DATE_FORMAT(NOW(), '%H') AS '24시간', -- 14
DATE_FORMAT(NOW(), '%h') AS '12시간', -- 02
DATE_FORMAT(NOW(), '%i') AS '분', -- 30
DATE_FORMAT(NOW(), '%s') AS '초', -- 25
DATE_FORMAT(NOW(), '%p') AS '오전/오후', -- PM
DATE_FORMAT(NOW(), '%r') AS '12시간형식'; -- 02:30:25 PM
알아두세요: MySQL의 날짜 형식 지정자는 %Y, %m 등으로 사용하며, Oracle의 ‘YYYY’, ‘MM’이나 MS-SQL의 ‘yyyy’, ‘mm’과 다릅니다.
5. MySQL 날짜 범위 다루기
월의 첫날/마지막날 구하기
-- 해당 월의 첫날
SELECT DATE_FORMAT(NOW(), '%Y-%m-01') AS '월의첫날'; -- 2025-03-01
-- 해당 월의 마지막날
SELECT LAST_DAY(NOW()) AS '월의마지막날'; -- 2025-03-31
-- 다음 달의 첫날
SELECT DATE_ADD(DATE_FORMAT(NOW(), '%Y-%m-01'), INTERVAL 1 MONTH) AS '다음달첫날'; -- 2025-04-01
-- 이전 달의 마지막날
SELECT DATE_SUB(DATE_FORMAT(NOW(), '%Y-%m-01'), INTERVAL 1 DAY) AS '이전달마지막날'; -- 2025-02-28
실무 활용: 월별 보고서 기간 설정, 월 단위 결제 주기 계산 등에 활용됩니다.
연도 및 분기의 시작/끝 구하기
-- 해당 연도의 첫날/마지막날
SELECT
DATE_FORMAT(NOW(), '%Y-01-01') AS '연도첫날', -- 2025-01-01
DATE_FORMAT(NOW(), '%Y-12-31') AS '연도마지막날'; -- 2025-12-31
-- 해당 분기의 첫날
SELECT
DATE_FORMAT(
DATE_SUB(NOW(), INTERVAL (MONTH(NOW())-1) % 3 MONTH),
'%Y-%m-01'
) AS '분기첫날'; -- 2025-01-01 (1분기)
-- 해당 분기의 마지막날
SELECT
LAST_DAY(
DATE_ADD(
DATE_FORMAT(
DATE_SUB(NOW(), INTERVAL (MONTH(NOW())-1) % 3 MONTH),
'%Y-%m-01'
),
INTERVAL 2 MONTH
)
) AS '분기마지막날'; -- 2025-03-31 (1분기)
분기별 계산: 회계 보고서나 분기별 목표 달성 보고서 작성 시 유용합니다.
일주일의 시작/끝 구하기
-- 현재 주의 월요일(한 주의 시작)
SELECT
DATE_SUB(NOW(), INTERVAL WEEKDAY(NOW()) DAY) AS '이번주월요일'; -- 2025-03-17 (월요일)
-- 현재 주의 일요일(한 주의 끝)
SELECT
DATE_ADD(DATE_SUB(NOW(), INTERVAL WEEKDAY(NOW()) DAY), INTERVAL 6 DAY) AS '이번주일요일'; -- 2025-03-23 (일요일)
주별 보고서: 주간 매출 보고서나 주간 활동 요약 작성 시 활용할 수 있습니다.
6. MySQL 실무 사례: 자주 사용되는 쿼리
오늘/어제/이번주/이번달 데이터 조회
-- 오늘 데이터 조회
SELECT * FROM orders
WHERE DATE(order_date) = CURDATE();
-- 어제 데이터 조회
SELECT * FROM orders
WHERE DATE(order_date) = DATE_SUB(CURDATE(), INTERVAL 1 DAY);
-- 이번 달 데이터 조회
SELECT * FROM orders
WHERE YEAR(order_date) = YEAR(CURDATE())
AND MONTH(order_date) = MONTH(CURDATE());
-- 지난 7일간 데이터 조회
SELECT * FROM orders
WHERE order_date >= DATE_SUB(NOW(), INTERVAL 7 DAY);
팁: DATE()를 사용하여 시간 부분을 제거하면 날짜 비교가 더 정확해집니다.
일별 트렌드 분석 (간결한 버전)
-- 최근 7일간 일별 주문 집계
SELECT
DATE(order_date) AS order_day,
COUNT(*) AS order_count,
SUM(total_amount) AS daily_sales
FROM
orders
WHERE
order_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY
DATE(order_date)
ORDER BY
order_day;
팁: 이 쿼리로 요일별 주문 패턴을 파악할 수 있습니다. 주말에 주문이 늘어나는지, 특정 요일에 매출이 집중되는지 확인 가능합니다.
월별 매출 비교 (작년 vs 올해)
-- 월별 매출 비교 (작년 vs 올해)
SELECT
MONTH(order_date) AS order_month,
SUM(CASE WHEN YEAR(order_date) = YEAR(DATE_SUB(CURDATE(), INTERVAL 1 YEAR))
THEN total_amount ELSE 0 END) AS last_year_sales,
SUM(CASE WHEN YEAR(order_date) = YEAR(CURDATE())
THEN total_amount ELSE 0 END) AS this_year_sales
FROM
orders
WHERE
order_date >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 YEAR), '%Y-01-01')
GROUP BY
MONTH(order_date)
ORDER BY
order_month;
성장률 분석: 이 쿼리로 작년 대비 올해 매출 성장을 쉽게 비교할 수 있습니다.
7. MySQL 시간 관련 함수
MySQL에서는 시간 관련 작업을 위한 다양한 함수들을 제공합니다.
시간 데이터 다루기
-- TIME 데이터 타입 사용
SELECT CURTIME() AS '현재시간'; -- 14:30:25
-- 시간 추출
SELECT
HOUR(CURTIME()) AS '시', -- 14
MINUTE(CURTIME()) AS '분', -- 30
SECOND(CURTIME()) AS '초'; -- 25
-- 초를 시:분:초 형식으로 변환
SELECT SEC_TO_TIME(3665) AS '시간변환'; -- 01:01:05 (3665초 = 1시간 1분 5초)
-- 시:분:초를 초로 변환
SELECT TIME_TO_SEC('01:01:05') AS '초변환'; -- 3665
활용 팁: SEC_TO_TIME과 TIME_TO_SEC는 작업 시간이나 처리 시간을 계산할 때 유용합니다.
시간 계산
-- 시간 더하기/빼기
SELECT
CURTIME() AS '현재', -- 14:30:25
ADDTIME(CURTIME(), '01:00:00') AS '1시간후', -- 15:30:25
SUBTIME(CURTIME(), '01:00:00') AS '1시간전'; -- 13:30:25
-- 시간 간격 더하기
SELECT
NOW() AS '현재', -- 2025-03-19 14:30:25
DATE_ADD(NOW(), INTERVAL '1:30' HOUR_MINUTE) AS '1시간30분후'; -- 2025-03-19 16:00:25
업무 활용: 업무 시간 계산, 예상 완료 시간 계산 등에 활용할 수 있습니다.
실무 사례: 시간 활용
-- 시간대별 주문 분석
SELECT
HOUR(order_time) AS hour_of_day,
CONCAT(LPAD(HOUR(order_time), 2, '0'), ':00-', LPAD(HOUR(order_time)+1, 2, '0'), ':00') AS time_slot,
COUNT(*) AS order_count
FROM
orders
WHERE
DATE(order_date) = CURDATE() -- 오늘 주문만
GROUP BY
HOUR(order_time)
ORDER BY
hour_of_day;
팁: 이 쿼리로 하루 중 주문이 가장 많은 시간대를 파악할 수 있습니다.
8. MySQL 날짜 관련 문제 해결
날짜 비교 주의사항
-- 시간 부분 포함된 날짜 비교 시 주의
SELECT
CASE
WHEN '2025-03-19 15:30:00' = '2025-03-19'
THEN '일치'
ELSE '불일치'
END AS result; -- '불일치' 반환 (시간 부분이 다름)
-- 올바른 방식 (날짜 부분만 비교)
SELECT
CASE
WHEN DATE('2025-03-19 15:30:00') = '2025-03-19'
THEN '일치'
ELSE '불일치'
END AS result; -- '일치' 반환
흔한 실수: 시간이 포함된 DATETIME과 날짜만 있는 문자열을 비교할 때 발생하는 가장 흔한 오류입니다. DATE() 함수를 사용하여 시간 부분을 제거한 후 비교해야 합니다.
월말 처리 문제
-- 월말 날짜 이슈
SELECT
'2025-01-31' AS "1월말",
DATE_ADD('2025-01-31', INTERVAL 1 MONTH) AS "1개월후"; -- 2025-02-28 (2월은 28일까지)
-- LAST_DAY 함수 활용
SELECT
LAST_DAY('2025-01-31') AS "1월마지막날", -- 2025-01-31
LAST_DAY('2025-02-01') AS "2월마지막날"; -- 2025-02-28
날짜 계산 주의: 월마다 일수가 다르기 때문에 월 단위 계산 시 예상과 다른 결과가 나올 수 있습니다. 월말 결제일 계산 시 LAST_DAY 함수를 활용할 수 있습니다.
윤년 처리
-- 윤년 여부 확인
CREATE FUNCTION is_leap_year(p_year INT)
RETURNS VARCHAR(1)
DETERMINISTIC
BEGIN
IF (p_year % 400 = 0) OR (p_year % 4 = 0 AND p_year % 100 <> 0) THEN
RETURN 'Y';
ELSE
RETURN 'N';
END IF;
END;
-- 사용 예
SELECT
is_leap_year(2024) AS "2024년", -- Y (윤년)
is_leap_year(2025) AS "2025년"; -- N (평년)
-- 2월 마지막 날 확인으로 윤년 확인
SELECT
DAY(LAST_DAY('2024-02-01')) AS "2024년2월마지막날", -- 29
DAY(LAST_DAY('2025-02-01')) AS "2025년2월마지막날"; -- 28
특정 날짜 유효성 검사: 사용자 입력 날짜의 유효성을 검사할 때 윤년 여부를 확인해야 합니다. LAST_DAY 함수를 사용하면 쉽게 확인할 수 있습니다.
이 글에서는 MySQL의 날짜 및 시간 함수에 대해 알아보았습니다. MySQL은 웹 애플리케이션에서 가장 많이 사용되는 데이터베이스로, 날짜와 시간을 효율적으로 다루는 것은 매우 중요합니다. 특히 DATE_FORMAT, STR_TO_DATE, DATE_ADD, DATEDIFF, TIMESTAMPDIFF, LAST_DAY 등의 함수는 MySQL에서 날짜 작업 시 가장 많이 사용되는 함수들이니 반드시 익혀두시길 추천드립니다. 추가 질문이나 특정 날짜 문제에 대한 도움이 필요하면 댓글로 남겨주세요! ~~