251028_BootCamp Day 7_SQL 날짜 & 서브쿼리
2025. 10. 28. 20:33ㆍTIL
1. SQL 날짜 연산 내장 함수
여러 사이트에 있는 SQL 문제를 풀면서, 생각보다 날짜(date, time) 관련한 연산이 많이 필요하다는 것을 알게 되었다.
데이터를 구분할 때 날짜를 기준으로 하는 경우가 많을 것 같다. (특정 기간에 발생한 이벤트, 일정 기간 이후 신규 가입자 등)
그런데 날짜를 계산하는 방식을 잘 모르다 보니, 이번 기회에 MySQL에서 사용하는 날짜 연산 내장 함수들에 대해 제대로 알아보기로 하였다.
현재 날짜 및 시간 조회
NOW() -- 현재 날짜와 시간 반환(YYYY-MM-DD HH:MM:SS)
CURDATE() -- 현재 날짜 반환(YYYY-MM-DD)
CURTIME() -- 현재 시간 반환(HH:MM:DD)
날짜 및 시간 덧셈/뺄셈
DATE_ADD(date, INTERVAL number unit) -- 일정 간격의 날짜 더하기
DATE_ADD('2025-10-28', INTERVAL 3 day) --2025-10-28에 3일을 더함 -> 2025-10-31
DATE_SUB(date, INTERVAL number unit) -- 일정 간격의 날짜 빼기
DATE_SUB('2025-10-28', INTERVAL 2 month) -- 2025-10-28에 2달을 뺌 -> 2025-08-28
날짜/시간 요소 추출
YEAR('2025-10-28') -- 날짜에서 연도 추출 -> 2025
MONTH('2025-10-28') -- 날짜에서 월 추출 -> 10
DAY('2025-10-28') -- 날짜에서 일 추출 -> 28
HOUR('17:08:12') -- 시간에서 시 추출 -> 17
MINUTE('17:08:12') -- 시간에서 분 추출 -> 8
SECOND('17:08:12') -- 시간에서 초 추출 -> 12
DAYNAME('2025-10-28') -- 날짜에서 요일 추출 -> Tuesday
DAYOFWEEK('2025-10-28') -- 날짜에서 요일 추출 후 숫자로 변환 -> 3(1:일요일 ~ 7:토요일)
EXTRACT(unit FROM date) -- 날짜에서 다양한 단위 추출
EXTRACT(year_month FROM '2025-10-28') -- 202510
EXTRACT(week FROM '2025-10-28') -- 44 (1년의 몇 주차인지)
날짜/시간 형식 변환(Formatting)
DATE_FORMAT(date, format) -- 날짜를 지정된 format의 문자열로 반환
DATE_FORMAT('2025-10-28 17:13:20', '%Y-%m-%d') -- 2025-10-28
DATE_FORMAT('2025-10-28 17:13:20', '%Y년 %m월 %d일 %H시 %i분') -- 2025년 10월 28일 17시 13분
STR_TO_DATE(str, format) -- 문자열을 지정된 형식을 기준으로 날짜 값으로 변환
STR_TO_DATE('2025-10-28', '%Y-%m-%d') -- 2025-10-28(date type)
날짜/시간 차이 계산
DATEDIFF(date1, date2) -- 두 날짜 사이의 일 수(days) 차이를 반환 (date1-date2)
DATEDIFF('2025-10-28', '2025-10-24') -- 4
TIEMDIFF(time1, time2) -- 두 시간 사이의 차이를 반환 (time1 - time2)
TIMEDIFF('17:30:00', '16:25:00') -- '1:05:00'
TIMESTAMPDIFF(unit, datetime_expr1, datetime_expr2) -- 두 날짜/시간 사이의 차이를 지정된 단위로 반환
2. 서브쿼리 (Subquery)
서브쿼리는 말 그대로 서브로 존재하는 쿼리이다.
아니 메인 쿼리 하나로 다 되는 거 아니었어? 아쉽게도 SQL은 그렇지가 않다.
실제로는 다뤄야 하는 컬럼들이 매우 많고, 그 컬럼들을 이용해서 다양한 연산을 한꺼번에 수행하다 보니, 서브쿼리를 이용해 각 연산들을 구조적으로 수행/기록해 최종적인 결과를 메인쿼리에서 만드는 경우가 많다.
N개의 쿼리를 작성해 모든 연산들을 따로 계산한 후에 결과값을 하나로 합치는 것보다는 하나의 쿼리에서 모든 작업을 수행하는 것이 훨씬 더 효율적이고, 가독성도 더 우수하기 때문이다.
서브쿼리의 특징
서브쿼리를 쓸 때는 반드시 괄호 ()를 이용해서 쿼리를 묶어주어야 한다.
서브쿼리의 끝에는 세미콜론(;)을 작성하면 안 된다.
ORDER BY 절을 사용하지 않는다.(사용할 수는 있으나, 특별히 의미가 없다.)
서브쿼리는 그 위치에 따라 중첩 서브쿼리, 스칼라 서브쿼리, 인라인 뷰로 나뉜다.

| 중첩(일반) 서브쿼리 | WHERE 절에서 사용 서브쿼리의 결과를 메인 컬럼을 필터링하는 조건으로 사용하고 싶을 때 상관 서브쿼리 : 메인 쿼리의 컬럼을 참조 ➡️ 메인 쿼리의 행과 하나씩 비교한다. 비상관 서브쿼리 : 메인 쿼리의 내용과 관련 없음 |
| 스칼라 서브쿼리 | SELECT 절에서 사용 서브쿼리의 결과를 하나의 컬럼처럼 사용하고 싶을 때 스칼라 서브쿼리는 보통 다른 테이블의 컬럼을 메인 쿼리에 쓰고 싶을 때 사용한다. |
| 인라인 뷰 | FROM 절에서 사용 서브쿼리를 하나의 테이블처럼 사용하고 싶을 때 가장 중요하고 가장 많이 쓰이는 서브쿼리 유형이다. 인라인 뷰는 as를 이용해 alias를 반드시 지정해줘야 한다. |
3. 서브쿼리 실습
서브쿼리의 활용
select a.first_login_date,
a.actor_cnt
from (
select first_login_date,
count(distinct game_actor_id) as actor_cnt
from basic.users
group by first_login_date
) as a
where a.actor_cnt > 10
;
기본적인 인라인 뷰를 사용한 쿼리이다. 인라인 뷰의 값을 메인 쿼리에서 추가적인 연산에 사용하지 않는다.
서브쿼리의 응용
select a.actor_cnt,
count(distinct game_account_id) as accnt
from
(
select game_account_id, count(distinct game_actor_id) as actor_cnt
from basic.users
where level >= 30
group by game_account_id
having count(distinct game_actor_id) >= 2
) as a
group by a.actor_cnt
;
인라인 뷰의 값을 이용해 메인 쿼리에서 연산을 하는, 조금 더 복잡한 형태의 쿼리이다.
'TIL' 카테고리의 다른 글
| 251030_BootCamp Day 9_파이썬의 여러 가지 기능들 (0) | 2025.10.30 |
|---|---|
| 251029_BootCamp Day 8_SQL 코딩테스트 문제 (0) | 2025.10.29 |
| 251027_BootCamp Day 6_Python 함수 / SQL 기본 (0) | 2025.10.27 |
| 251024_BootCamp Day 5_Python 조건문, 반복문 (1) | 2025.10.24 |
| 251023_BootCamp Day 4_데이터 리터러시 2 (0) | 2025.10.23 |