MySQL DateTime 포맷과 문자열 날짜값의 비교, 그리고 date_format() 날짜 포매팅

MySQL(MariaDB)의 날짜 정보 저장 필드는 보통 DateTime 포맷을 사용합니다.

데이터는 밀리세컨드 단위까지 저장되는 타임틱 값이기 때문에 쿼리문으로 선택을 해야 날짜 포맷으로 표시가 됩니다.

반면 실제 웹개발을 할 때 날짜, 또는 시간 값을 입력받아 쿼리문으로 비교를 하는 경우

"2019-11-23" 과 같은 문자열로 입력을 받아 서버로 전송하는 것이 일반적입니다.

전송된 날짜 문자열을 DateTime 필드와 비교를 하려면 

1. 서버로 전송한 문자열을 날짜 포맷으로 변환해 DateTime 필드와 비교하거나, 

2. DateTime 필드의 시간값을 "yyyy-mm-dd" 10자리 문자열로 변환해 문자열을 비교해야 합니다.

결론부터 말하면 1번이 실행 속도면에서는 미세하게 더 빠릅니다.

다만, 가독성이나 사용성 측면에서는 2번이 더 편하고 활용하기 좋을 때도 있습니다.

1. 문자열을 날짜 포맷으로 변환해 DateTime 필드값과 비교

MySQL 내장 함수인 str_to_date('문자열', '포맷문자열') 을 사용합니다.

예를 들어

select wt from test where wt > str_to_date('2019-11-20', '%Y-%m-%d');

와 같이 쿼리문을 작성했다면 아래와 같은 결과를 리턴합니다.

2. DateTime 필드를 문자열로 변환해 문자열로 비교

MySQL 내장 함수인 date_format(datetime필드명, '포맷문자열') 을 사용합니다.

예를들어 

select date_format(wt, '%Y-%m-%d') as ymd10 from test;

와 같이 쿼리문을 작성했다면

test 테이블의 datetime 필드인 wt를 'yyyy-mm-dd' 형태의 문자열로 선택해 "ymd10" 컬럼명으로 결과를 리턴합니다.

사용자 입력 필드값으로 'yyyy-mm-dd' 형태의 년월일 문자열을 입력받아 wt 필드와 비교를 하되 wt 필드의 값을 'yyyy-mm-dd' 포맷으로 변환해 문자열 비교를 하면 위의 결과에서 "2019-11-20" 이후의 wt 필드 값만을 리턴하게 됩니다.

select wt from test where date_format(wt, '%Y-%m-%d') > '2019-11-20';

3. 비교하는 방식에 따라 결과값이 달라질 수 있다.

1번의 

select wt from test where wt > str_to_date('2019-11-20', '%Y-%m-%d');

와 2번의 

select wt from test where date_format(wt, '%Y-%m-%d') > '2019-11-20';

는 언뜻 같아보이지만 리턴하는 결과값은 다릅니다.

비교 기준이 문자열이나 datetime 값이냐에 따라 비교 기준이 전혀 달라지며, 최대 1일의 차이를 가지게 됩니다.

1번은 비교 기준이 날짜값입니다. 따라서 '2019-11-20' 문자열은 2019-11-20 00:00:00 (2019년 11월 20일 자정)인 datetime 포맷이 되고, 이것보다 날짜가 최근인 3개의 레코드를 리턴합니다.(wt 필드의 2019년 11월 20일인 필드가 모두 포함됨)

반면 2번은 비교기준이 문자열이 되고 wt 필드의 datetime 값은 시분초가 잘려나간 10자리 문자열이 됩니다. 따라서 '2019-11-20' 보다 큰 문자열을 가진 필드만 리턴하므로 '2019-11-20'은 제외가 되기 때문에 리턴되는 레코드수가 그만큼 줄어들게 되는 것입니다.

(wt 필드의 2019년 11월 20일인 필드는 모두 제외됨)

* DATE_FORMAT() 파라메터 예

 '%W, %M %Y'

Saturday, November 2019

Wednesday, November 2019

Thursday, November 2019

 '%h:%i:%s'

11:34:35

 '%p %h:%i'

PM 11:34

AM 10:05



* DATE_FORMAT() 파라메터 레퍼런스

파라메터

설명
%a 3글자 요일 영문자 (Sun..Sat)
%b 3글자 월 영문자 (Jan..Dec)
%c

숫자 월 (0..12)

%D

영어 서수로 날짜 표시 (0th, 1st, 2nd, 3rd, …)

%d

숫자 날짜 2자리(0채움) (00..31)

%e 숫자 날짜 (0..31)
%f 마이크로세컨드 (000000..999999)
%H 24시간 시(0채움) (00..23)
%h 12시간 시(0채움) (01..12)
%I 12시간 시(0채움) (01..12)
%i 2자리 분(0채움) (00..59)
%j 1년의 몇번째날(0채움) (001..366)
%k

24시간 시 (0..23)

%l

12시간 시 (1..12)

%M

영문 월 전체길이 (January..December)

%m 숫자 월(0채움) (00..12)
%p

AM 또는 PM

%r

12시간 단위 AM/PM 시:분:초 (AM 또는 PM 뒤에 hh:mm:ss)

%S 초(0채움) (00..59)
%s 초(0채움)(00..59)
%T Time, 24-hour (hh:mm:ss)
%U

올해의 몇번째주(2자리 0채움) (00..53) - 일요일이 주의 첫요일임. week() 모드 1

%u

올해의 몇번째주(2자리 0채움) (00..53), 월요일이 주의 첫요일임. week() 모드 2

%V

올해의 몇번째주(0채움) (01..53), 일요일이 주의 첫번째 날임. WEEK() 모드 2; %X 와 함께 사용

%v

올해의 몇번째주(0채움) (01..53), 월요일이 주의 첫번째 날임. WEEK() 모드 3; %x 와 함께 사용

%W

전체 길이 영문 요일 (Sunday..Saturday)

%w 요일 순서 숫자 (0=일요일..6=토요일)
%X

일요일이 첫요일인 주 표시를 위한 4자리 숫자 년도, %V 와 함께 사용(일요일부터 시작하는 2019년도 첫째주)

%x

월요일이 첫요일인 주 표시를 위한 4자리 숫자 년도, %v 와 함께 사용(월요일부터 시작하는 2019년도 첫째주)

%Y 4자리 년도
%y 2자리 년도
%% %문자 표시