DATEDIFF retorna o número de dias, meses ou outras unidades entre duas datas. Cada banco de dados faz isso de um jeito, e os exemplos cobrem PostgreSQL, MySQL, SQLite e SQL Server.
Como usar o DATEDIFF
DATEDIFF conta os dias, meses, anos ou outras unidades de uma data inicial até uma data final. Esta é a versão do SQL Server, a que a maioria das pessoas tem em mente:
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
A unidade pode ser year, quarter, month, week, day, hour, minute, second ou menor. Quando a data final vem antes da inicial, o resultado é negativo.
Com colunas, você obtém uma diferença por linha:
-- 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
Regras importantes
-
Ele conta limites, não unidades inteiras.
DATEDIFF(month, ...)conta as viradas de mês entre as duas datas, então um único dia pode contar como um mês, ou um ano:
SELECT DATEDIFF(month, '2026-01-31', '2026-02-01');
-- Output: 1
SELECT DATEDIFF(year, '2025-12-31', '2026-01-01');
-- Output: 1
-
Entra NULL, sai NULL. Se qualquer uma das datas for NULL, o resultado também será, como o pedido 1004 acima. Envolva a chamada em
COALESCE()quando precisar de um valor padrão.
Sintaxe alternativa
O MySQL tem um DATEDIFF com dois argumentos que só conta dias e recebe a data final primeiro. Para qualquer outra unidade, use TIMESTAMPDIFF, que recebe a data inicial primeiro e conta unidades inteiras:
SELECT DATEDIFF('2026-03-15', '2026-01-01');
-- Output: 73
SELECT TIMESTAMPDIFF(MONTH, '2026-01-01', '2026-03-15');
-- Output: 2
O PostgreSQL não tem DATEDIFF. Subtraia uma data da outra para obter os dias. Para unidades maiores, AGE() (data mais recente primeiro) retorna um intervalo em anos, meses e dias, e EXTRACT extrai unidades inteiras dele:
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
O SQLite também não tem DATEDIFF. julianday() transforma uma data em um número de dias, então subtrair dois deles dá a diferença. CAST(... AS INTEGER) descarta a fração, e não há unidade de mês ou ano, então divida por 30 ou 365 para ter uma aproximação:
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
Quando usar o DATEDIFF?
A maioria das perguntas sobre diferença entre datas se encaixa em um destes quatro casos.
Medir quanto tempo algo levou
Subtraia uma data inicial de uma data final para obter uma duração: os dias para enviar um pedido, as semanas que um projeto durou, os minutos de uma ligação de suporte.
Contar dias de atraso ou restantes
Compare um prazo com hoje, ou com uma data de referência fixa, para ver o quanto algo está atrasado ou quanto tempo falta. Filtre pelo sinal do resultado para ficar com um dos lados.
Expressar uma idade em meses ou anos
Idade de conta, tempo de cliente e tempo de serviço exigem uma unidade maior que dias. Use uma unidade de mês ou ano quando seu banco de dados tiver uma. No SQLite, divida os dias.
Encontrar linhas dentro de uma janela em torno de uma data
Use o valor absoluto da diferença para encontrar linhas a até certo número de dias de uma data, antes ou depois dela: eventos próximos a um lançamento, logins em torno de um incidente.
Exemplos reais de DATEDIFF
Verificar tickets de suporte contra um SLA
Cada ticket deve ser resolvido em até três dias. Conte os dias que cada um levou e sinalize as violações (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
Listar faturas vencidas
Mostre as faturas após o vencimento, das mais atrasadas para as menos (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
Agrupar clientes pelo tempo de relacionamento
Coloque os clientes em faixas pelo tempo de relacionamento em anos completos (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
Encontrar assinaturas próximas da renovação
Liste as assinaturas que terminam nos próximos 30 dias, com os dias restantes (SQL Server). A cláusula WHERE compara subscription_end com um intervalo de datas em vez de envolvê-la em DATEDIFF, assim um índice na coluna ainda pode ser usado.
-- 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
Leitura complementar sobre DATEDIFF
Neste blog:
-
Guia de formatação de datas no SQL: transformando datas em texto com
strftime,TO_CHAR,DATE_FORMATeFORMAT - Guia de inserção de datas no SQL: tipos de data e como inserir valores de data
- Como subtrair no SQL: subtraindo números, datas e timestamps
-
Como subtrair no PostgreSQL: aritmética de datas e timestamps, incluindo
age() -
Operações de subtração no SQLite: diferenças entre datas com
julianday() - Extrair o total de dias, horas ou minutos de um intervalo no PostgreSQL: transformando intervalos em números
- Guia de COALESCE no SQL: valores padrão para datas NULL
Documentação oficial:
- PostgreSQL: funções e operadores de data/hora
- MySQL: DATEDIFF() e TIMESTAMPDIFF()
- SQLite: funções de data e hora
- SQL Server: DATEDIFF
Beekeeper Studio é um cliente de banco de dados gratuito e open source
A melhor ferramenta de consultas e edição de SQL que já usei. Tem tudo o que preciso para gerenciar meu banco de dados. - ⭐⭐⭐⭐⭐ Mit
O Beekeeper Studio é rápido, intuitivo e fácil de usar. Ele suporta vários bancos de dados e funciona muito bem no Windows, Mac e Linux.
O que os usuários dizem sobre o Beekeeper Studio
"O Beekeeper Studio substituiu completamente meu antigo fluxo de trabalho com SQL. É rápido, intuitivo e torna o trabalho com bancos de dados agradável de novo."
"Já testei muitas GUIs de banco de dados, mas o Beekeeper tem o equilíbrio perfeito entre recursos e simplicidade. Simplesmente funciona."