DATEDIFF는 두 날짜 사이의 일, 월 또는 다른 단위의 수를 반환해요. 데이터베이스마다 방식이 다르기 때문에 PostgreSQL, MySQL, SQLite, SQL Server 예제를 모두 다뤄요.
DATEDIFF 사용법
DATEDIFF는 시작 날짜부터 종료 날짜까지의 일, 월, 연 또는 다른 단위를 세요. 대부분의 사람들이 말하는 DATEDIFF는 다음과 같은 SQL Server 버전이에요:
DATEDIFF(unit, start_date, end_date)
SELECT DATEDIFF(day, '2026-01-01', '2026-03-15');
-- Output: 73
SELECT DATEDIFF(month, '2026-01-01', '2026-03-15');
-- Output: 2
SELECT DATEDIFF(day, '2026-03-15', '2026-01-01');
-- Output: -73
단위로는 year, quarter, month, week, day, hour, minute, second 또는 더 작은 단위를 쓸 수 있어요. 종료 날짜가 시작 날짜보다 앞서면 결과는 음수가 돼요.
컬럼을 사용하면 행마다 차이가 하나씩 나와요:
-- Input: orders
-- order_id | order_date | ship_date
-- ---------+------------+-----------
-- 1001 | 2026-02-02 | 2026-02-04
-- 1002 | 2026-02-03 | 2026-02-10
-- 1003 | 2026-02-27 | 2026-03-02
-- 1004 | 2026-03-05 | NULL
SELECT
order_id,
order_date,
ship_date,
DATEDIFF(day, order_date, ship_date) AS fulfillment_days
FROM orders;
-- Output:
-- order_id | order_date | ship_date | fulfillment_days
-- ---------+------------+------------+-----------------
-- 1001 | 2026-02-02 | 2026-02-04 | 2
-- 1002 | 2026-02-03 | 2026-02-10 | 7
-- 1003 | 2026-02-27 | 2026-03-02 | 3
-- 1004 | 2026-03-05 | NULL | NULL
알아 둘 규칙
-
완전한 단위가 아니라 경계를 세요.
DATEDIFF(month, ...)는 두 날짜 사이의 월 경계를 세기 때문에, 단 하루 차이도 1개월이나 1년으로 계산될 수 있어요:
SELECT DATEDIFF(month, '2026-01-31', '2026-02-01');
-- Output: 1
SELECT DATEDIFF(year, '2025-12-31', '2026-01-01');
-- Output: 1
-
NULL이 들어가면 NULL이 나와요. 위의 주문 1004처럼 두 날짜 중 하나라도 NULL이면 결과도 NULL이에요. 기본값이 필요하면 호출을
COALESCE()로 감싸세요.
다른 문법
MySQL에는 인수가 두 개인 DATEDIFF가 있는데, 일 수만 세고 종료 날짜를 먼저 받아요. 다른 단위가 필요하면 TIMESTAMPDIFF를 사용하세요. 이 함수는 시작 날짜를 먼저 받고 완전한 단위만 세요:
SELECT DATEDIFF('2026-03-15', '2026-01-01');
-- Output: 73
SELECT TIMESTAMPDIFF(MONTH, '2026-01-01', '2026-03-15');
-- Output: 2
PostgreSQL에는 DATEDIFF가 없어요. 날짜끼리 빼면 일 수를 얻을 수 있어요. 더 큰 단위가 필요하면 AGE()(나중 날짜를 먼저)가 연, 월, 일로 된 interval을 반환하고, EXTRACT로 거기서 완전한 단위를 꺼낼 수 있어요:
SELECT DATE '2026-03-15' - DATE '2026-01-01';
-- Output: 73
SELECT AGE('2026-03-15', '2026-01-01');
-- Output: 2 mons 14 days
SELECT EXTRACT(YEAR FROM AGE('2026-03-15', '2026-01-01')) * 12
+ EXTRACT(MONTH FROM AGE('2026-03-15', '2026-01-01'));
-- Output: 2
SQLite에도 DATEDIFF가 없어요. julianday()는 날짜를 일 수로 바꿔 주므로 두 값을 빼면 차이가 나와요. CAST(... AS INTEGER)로 소수점을 버리고, 월이나 연 단위가 없으니 대략적인 값이 필요하면 30이나 365로 나누세요:
SELECT julianday('2026-03-15') - julianday('2026-01-01');
-- Output: 73.0
SELECT CAST((julianday('2026-03-15') - julianday('2026-01-01')) / 30 AS INTEGER);
-- Output: 2
-- The time of day counts: 8 p.m. to 8 a.m. is half a day.
-- Wrap each value in date() to count calendar days instead.
SELECT julianday('2026-03-16 08:00') - julianday('2026-03-15 20:00');
-- Output: 0.5
-- A date it can't read gives NULL, so store dates as YYYY-MM-DD
SELECT julianday('03/15/2026');
-- Output: NULL
DATEDIFF는 언제 사용하나요?
날짜 차이에 관한 질문은 대부분 다음 네 가지 중 하나에 해당해요.
걸린 시간 측정하기
종료 날짜에서 시작 날짜를 빼면 기간을 구할 수 있어요. 주문 배송에 걸린 일 수, 프로젝트가 진행된 주 수, 고객 지원 통화가 이어진 분 수 같은 것들이요.
연체 일수 또는 남은 일수 세기
마감일을 오늘이나 고정된 보고 기준일과 비교하면 얼마나 늦었는지, 또는 시간이 얼마나 남았는지 알 수 있어요. 결과의 부호로 필터링하면 한쪽만 남길 수 있어요.
나이를 월이나 연 단위로 표현하기
계정 사용 기간, 고객 유지 기간, 근속 기간에는 일보다 큰 단위가 필요해요. 데이터베이스에 월이나 연 단위가 있으면 그걸 사용하세요. SQLite에서는 일 수를 나누면 돼요.
특정 날짜 전후 범위의 행 찾기
차이의 절댓값을 구하면 특정 날짜 전후 며칠 안에 있는 행을 찾을 수 있어요. 출시 즈음의 이벤트, 장애 전후의 로그인 같은 것들이요.
DATEDIFF 실전 예제
지원 티켓의 SLA 준수 여부 확인하기
모든 티켓은 3일 안에 해결되어야 해요. 티켓마다 걸린 일 수를 세고 위반 건을 표시해 보세요(SQLite):
-- Input: support_tickets
-- ticket_id | created_at | resolved_at
-- ----------+------------+------------
-- 301 | 2026-03-02 | 2026-03-03
-- 302 | 2026-03-04 | 2026-03-07
-- 303 | 2026-03-05 | 2026-03-10
SELECT
ticket_id,
created_at,
resolved_at,
CAST(julianday(resolved_at) - julianday(created_at) AS INTEGER) AS resolution_days,
CASE
WHEN julianday(resolved_at) - julianday(created_at) <= 3 THEN 'Within SLA'
ELSE 'SLA Breach'
END AS sla_status
FROM support_tickets;
-- Output:
-- ticket_id | created_at | resolved_at | resolution_days | sla_status
-- ----------+------------+-------------+-----------------+-----------
-- 301 | 2026-03-02 | 2026-03-03 | 1 | Within SLA
-- 302 | 2026-03-04 | 2026-03-07 | 3 | Within SLA
-- 303 | 2026-03-05 | 2026-03-10 | 5 | SLA Breach
연체된 인보이스 목록
마감일이 지난 인보이스를 가장 오래 연체된 순서대로 보여 주세요(MySQL):
-- Input: invoices
-- invoice_id | customer | due_date
-- -----------+---------------+-----------
-- 5001 | Acme Hardware | 2026-08-15
-- 5002 | Lumen Design | 2026-09-30
-- 5003 | Acme Hardware | 2026-10-01
-- 5004 | Cedar Clinic | 2026-10-31
SELECT
invoice_id,
customer,
due_date,
DATEDIFF(CURDATE(), due_date) AS days_overdue
FROM invoices
WHERE due_date < CURDATE()
ORDER BY days_overdue DESC;
-- Output (run on 2026-10-13):
-- invoice_id | customer | due_date | days_overdue
-- -----------+---------------+------------+-------------
-- 5001 | Acme Hardware | 2026-08-15 | 59
-- 5002 | Lumen Design | 2026-09-30 | 13
-- 5003 | Acme Hardware | 2026-10-01 | 12
이용 기간별로 고객 그룹 나누기
고객을 만 연 단위 이용 기간에 따라 등급으로 나눠 보세요(PostgreSQL):
-- Input: customers
-- customer_name | signup_date
-- ------------------+------------
-- Northwind Traders | 2022-11-05
-- Bluebird Bakery | 2025-06-20
-- Fjord Outfitters | 2025-12-20
-- Kestrel Labs | 2026-03-02
SELECT
customer_name,
signup_date,
EXTRACT(YEAR FROM AGE(CURRENT_DATE, signup_date)) AS years_with_us,
CASE
WHEN AGE(CURRENT_DATE, signup_date) < INTERVAL '1 year' THEN 'New'
WHEN AGE(CURRENT_DATE, signup_date) < INTERVAL '2 years' THEN 'Established'
ELSE 'Loyal'
END AS customer_tier
FROM customers;
-- Output (run on 2026-10-13):
-- customer_name | signup_date | years_with_us | customer_tier
-- ------------------+-------------+---------------+--------------
-- Northwind Traders | 2022-11-05 | 3 | Loyal
-- Bluebird Bakery | 2025-06-20 | 1 | Established
-- Fjord Outfitters | 2025-12-20 | 0 | New
-- Kestrel Labs | 2026-03-02 | 0 | New
갱신 예정인 구독 찾기
앞으로 30일 안에 끝나는 구독을 남은 일수와 함께 나열해 보세요(SQL Server). WHERE 절에서 subscription_end를 DATEDIFF로 감싸지 않고 날짜 범위와 직접 비교하기 때문에, 해당 컬럼의 인덱스를 계속 활용할 수 있어요.
-- Input: subscriptions
-- customer_name | subscription_end
-- -----------------+-----------------
-- Harbor Dental | 2026-10-09
-- Maple Yoga | 2026-10-20
-- Orbit Analytics | 2026-11-07
-- Pinecrest Realty | 2027-01-15
SELECT
customer_name,
subscription_end,
DATEDIFF(day, GETDATE(), subscription_end) AS days_remaining
FROM subscriptions
WHERE subscription_end BETWEEN CAST(GETDATE() AS date)
AND DATEADD(day, 30, CAST(GETDATE() AS date))
ORDER BY days_remaining;
-- Output (run on 2026-10-13):
-- customer_name | subscription_end | days_remaining
-- ----------------+------------------+---------------
-- Maple Yoga | 2026-10-20 | 7
-- Orbit Analytics | 2026-11-07 | 25
DATEDIFF 관련 추가 자료
이 블로그의 글:
-
SQL 날짜 형식 가이드:
strftime,TO_CHAR,DATE_FORMAT,FORMAT으로 날짜를 텍스트로 바꾸기 - SQL 날짜 삽입 가이드: 날짜 타입과 날짜 값을 삽입하는 방법
- SQL에서 빼기 연산하는 방법: 숫자, 날짜, 타임스탬프 빼기
-
PostgreSQL에서 빼기 연산하는 방법:
age()를 포함한 날짜와 타임스탬프 연산 -
SQLite 빼기 연산:
julianday()로 날짜 차이 구하기 - PostgreSQL interval에서 총 일, 시간, 분 추출하기: interval을 숫자로 바꾸기
- SQL COALESCE 가이드: NULL 날짜에 기본값 지정하기
공식 문서:
- PostgreSQL: 날짜/시간 함수와 연산자
- MySQL: DATEDIFF() 및 TIMESTAMPDIFF()
- SQLite: 날짜와 시간 함수
- SQL Server: DATEDIFF
Beekeeper Studio는 무료 오픈 소스 데이터베이스 GUI예요
지금까지 써 본 SQL 쿼리 & 에디터 도구 중 최고예요. 데이터베이스 관리에 필요한 모든 게 다 있어요. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio는 빠르고 직관적이며 사용하기 쉬워요. 다양한 데이터베이스를 지원하고 Windows, Mac, Linux에서 모두 잘 작동해요.
Beekeeper Studio 사용자 후기
"Beekeeper Studio가 예전 SQL 작업 방식을 완전히 대체했어요. 빠르고 직관적이라 데이터베이스 작업이 다시 즐거워졌어요."
"여러 데이터베이스 GUI를 써 봤지만, Beekeeper는 기능과 단순함 사이의 균형이 완벽해요. 그냥 잘 돌아가요."