DATEDIFF restituisce il numero di giorni, mesi o altre unità tra due date. Ogni database lo fa a modo suo, e gli esempi coprono PostgreSQL, MySQL, SQLite e SQL Server.
Come usare DATEDIFF
DATEDIFF conta i giorni, i mesi, gli anni o altre unità da una data di inizio a una data di fine. Questa è la versione di SQL Server, quella a cui pensa la maggior parte delle persone:
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
L'unità può essere year, quarter, month, week, day, hour, minute, second o più piccola. Se la data di fine viene prima di quella di inizio, il risultato è negativo.
Con le colonne ottieni una differenza per ogni riga:
-- 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
Regole da conoscere
-
Conta i confini, non le unità intere.
DATEDIFF(month, ...)conta i passaggi di mese tra le due date, quindi anche un solo giorno può valere un mese, o un anno:
SELECT DATEDIFF(month, '2026-01-31', '2026-02-01');
-- Output: 1
SELECT DATEDIFF(year, '2025-12-31', '2026-01-01');
-- Output: 1
-
NULL in ingresso, NULL in uscita. Se una delle due date è NULL, lo è anche il risultato, come per l'ordine 1004 qui sopra. Racchiudi la chiamata in
COALESCE()quando ti serve un valore predefinito.
Sintassi alternative
MySQL ha un DATEDIFF a due argomenti che conta solo i giorni e vuole prima la data di fine. Per qualsiasi altra unità usa TIMESTAMPDIFF, che vuole prima la data di inizio e conta le unità intere:
SELECT DATEDIFF('2026-03-15', '2026-01-01');
-- Output: 73
SELECT TIMESTAMPDIFF(MONTH, '2026-01-01', '2026-03-15');
-- Output: 2
PostgreSQL non ha DATEDIFF. Sottrai una data dall'altra per ottenere i giorni. Per unità più grandi, AGE() (prima la data più recente) restituisce un intervallo in anni, mesi e giorni, ed EXTRACT ne estrae le unità intere:
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
Nemmeno SQLite ha DATEDIFF. julianday() trasforma una data in un numero di giorni, quindi sottraendone due ottieni la differenza. CAST(... AS INTEGER) elimina la parte decimale e, non esistendo unità per mesi o anni, dividi per 30 o 365 per un valore approssimato:
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 usare DATEDIFF?
La maggior parte delle domande sulle differenze tra date rientra in uno di questi quattro casi.
Misurare quanto è durato qualcosa
Sottrai una data di inizio da una data di fine per ottenere una durata: i giorni per spedire un ordine, le settimane di un progetto, i minuti di una chiamata al supporto.
Contare i giorni di ritardo o quelli rimanenti
Confronta una scadenza con oggi, o con una data di riferimento fissa, per vedere quanto è in ritardo qualcosa o quanto tempo resta. Filtra sul segno del risultato per tenere solo un lato.
Esprimere un'età in mesi o anni
Età dell'account, anzianità del cliente e anni di servizio richiedono un'unità più grande dei giorni. Usa un'unità in mesi o anni se il tuo database ce l'ha. In SQLite, dividi i giorni.
Trovare righe in una finestra attorno a una data
Prendi il valore assoluto della differenza per trovare le righe entro un certo numero di giorni da una data, prima o dopo: eventi vicini a un lancio, login attorno a un incidente.
Esempi reali di DATEDIFF
Verificare i ticket di supporto rispetto a uno SLA
Ogni ticket deve essere risolto entro tre giorni. Conta i giorni impiegati per ciascuno e segnala le violazioni (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
Elencare le fatture scadute
Mostra le fatture oltre la scadenza, dalla più in ritardo (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
Raggruppare i clienti in base a da quanto tempo sono con te
Suddividi i clienti in fasce in base agli anni completi di anzianità (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
Trovare gli abbonamenti in scadenza
Elenca gli abbonamenti che scadono nei prossimi 30 giorni, con i giorni rimanenti (SQL Server). La clausola WHERE confronta subscription_end con un intervallo di date invece di racchiuderla in DATEDIFF, così un indice sulla colonna può ancora essere usato.
-- 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
Approfondimenti su DATEDIFF
Su questo blog:
-
Guida al formato delle date in SQL: trasformare le date in testo con
strftime,TO_CHAR,DATE_FORMATeFORMAT - Guida all'inserimento di date in SQL: tipi di data e come inserire valori di data
- Come sottrarre in SQL: sottrarre numeri, date e timestamp
-
Come sottrarre in PostgreSQL: aritmetica di date e timestamp, incluso
age() -
Operazioni di sottrazione in SQLite: differenze tra date con
julianday() - Estrarre il totale di giorni, ore o minuti da un intervallo PostgreSQL: trasformare gli intervalli in numeri
- Guida a SQL COALESCE: valori predefiniti per le date NULL
Documentazione ufficiale:
- PostgreSQL: funzioni e operatori di data/ora
- MySQL: DATEDIFF() e TIMESTAMPDIFF()
- SQLite: funzioni di data e ora
- SQL Server: DATEDIFF
Beekeeper Studio è una GUI per database gratuita & open source
Il miglior strumento per query & editor SQL che abbia mai usato. Offre tutto ciò che mi serve per gestire il mio database. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio è veloce, intuitivo e facile da usare. Beekeeper supporta tantissimi database e funziona alla grande su Windows, Mac e Linux.
Cosa dicono gli utenti di Beekeeper Studio
"Beekeeper Studio ha sostituito completamente il mio vecchio flusso di lavoro SQL. È veloce, intuitivo e rende di nuovo piacevole lavorare con i database."
"Ho provato molte GUI per database, ma Beekeeper trova l'equilibrio perfetto tra funzionalità e semplicità. Funziona e basta."