DATEDIFF liefert die Anzahl der Tage, Monate oder anderer Einheiten zwischen zwei Datumswerten. Jede Datenbank macht das anders – die Beispiele decken PostgreSQL, MySQL, SQLite und SQL Server ab.
So verwendest du DATEDIFF
DATEDIFF zählt die Tage, Monate, Jahre oder andere Einheiten von einem Start- bis zu einem Enddatum. Das hier ist die Version von SQL Server, die die meisten meinen:
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
Als Einheit gehen year, quarter, month, week, day, hour, minute, second oder kleinere. Liegt das Enddatum vor dem Startdatum, ist das Ergebnis negativ.
Mit Spalten bekommst du eine Differenz pro Zeile:
-- 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
Wichtige Regeln
-
Es zählt Grenzen, keine ganzen Einheiten.
DATEDIFF(month, ...)zählt die Monatsgrenzen zwischen den beiden Datumswerten, sodass schon ein einziger Tag als Monat zählen kann – oder als Jahr:
SELECT DATEDIFF(month, '2026-01-31', '2026-02-01');
-- Output: 1
SELECT DATEDIFF(year, '2025-12-31', '2026-01-01');
-- Output: 1
-
NULL rein, NULL raus. Ist eines der Datumswerte NULL, ist auch das Ergebnis NULL, wie bei Bestellung 1004 oben. Pack den Aufruf in
COALESCE(), wenn du einen Standardwert brauchst.
Alternative Syntax
MySQL hat ein DATEDIFF mit zwei Argumenten, das nur Tage zählt und das Enddatum zuerst erwartet. Für jede andere Einheit nimmst du TIMESTAMPDIFF, das das Startdatum zuerst erwartet und ganze Einheiten zählt:
SELECT DATEDIFF('2026-03-15', '2026-01-01');
-- Output: 73
SELECT TIMESTAMPDIFF(MONTH, '2026-01-01', '2026-03-15');
-- Output: 2
PostgreSQL hat kein DATEDIFF. Zieh ein Datum vom anderen ab, um die Tage zu bekommen. Für größere Einheiten liefert AGE() (späteres Datum zuerst) ein Intervall in Jahren, Monaten und Tagen, und EXTRACT holt ganze Einheiten daraus:
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 hat auch kein DATEDIFF. julianday() wandelt ein Datum in eine Anzahl von Tagen um, also ergibt die Subtraktion zweier Werte die Differenz. CAST(... AS INTEGER) schneidet die Nachkommastellen ab, und da es keine Monats- oder Jahreseinheit gibt, teilst du für einen Näherungswert durch 30 oder 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
Wann solltest du DATEDIFF verwenden?
Die meisten Fragen zu Datumsdifferenzen fallen in eine dieser vier Kategorien.
Messen, wie lange etwas gedauert hat
Zieh ein Startdatum von einem Enddatum ab, um eine Dauer zu bekommen: die Tage bis zum Versand einer Bestellung, die Wochen eines Projekts, die Minuten eines Support-Anrufs.
Überfällige oder verbleibende Tage zählen
Vergleiche eine Deadline mit heute oder einem festen Stichtag, um zu sehen, wie spät etwas dran ist oder wie viel Zeit noch bleibt. Filtere nach dem Vorzeichen des Ergebnisses, um nur eine Seite zu behalten.
Ein Alter in Monaten oder Jahren angeben
Kontoalter, Kundenzugehörigkeit und Dienstzeit brauchen eine größere Einheit als Tage. Nutze eine Monats- oder Jahreseinheit, wenn deine Datenbank eine hat. In SQLite teilst du die Tage.
Zeilen in einem Zeitfenster um ein Datum finden
Nimm den Absolutwert der Differenz, um Zeilen innerhalb einer bestimmten Anzahl von Tagen vor oder nach einem Datum zu finden: Events rund um einen Launch, Logins rund um einen Vorfall.
Praxisbeispiele für DATEDIFF
Support-Tickets gegen ein SLA prüfen
Jedes Ticket muss innerhalb von drei Tagen gelöst sein. Zähl die Tage pro Ticket und markiere die Verstöße (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
Überfällige Rechnungen auflisten
Zeig die Rechnungen nach Fälligkeit, die am längsten überfälligen zuerst (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
Kunden nach Dauer der Kundenbeziehung gruppieren
Teile Kunden nach ihrer Zugehörigkeit in vollen Jahren in Stufen ein (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
Abos finden, die bald verlängert werden
Liste die Abos auf, die in den nächsten 30 Tagen enden, samt verbleibender Tage (SQL Server). Die WHERE-Klausel vergleicht subscription_end mit einem Datumsbereich, statt die Spalte in DATEDIFF zu packen – so kann ein Index auf der Spalte weiter genutzt werden.
-- 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
Weiterführendes zu DATEDIFF
In diesem Blog:
-
SQL Date Format Guide: Datumswerte in Text umwandeln mit
strftime,TO_CHAR,DATE_FORMATundFORMAT - SQL Insert Date Guide: Datumstypen und wie du Datumswerte einfügst
- Subtrahieren in SQL: Zahlen, Datumswerte und Timestamps subtrahieren
-
Subtrahieren in PostgreSQL: Datums- und Timestamp-Arithmetik, inklusive
age() -
Subtraktion in SQLite: Datumsdifferenzen mit
julianday() - Gesamte Tage, Stunden oder Minuten aus einem PostgreSQL-Intervall extrahieren: Intervalle in Zahlen umwandeln
- SQL COALESCE Guide: Standardwerte für NULL-Datumswerte
Offizielle Dokumentation:
- PostgreSQL: Date/Time Functions and Operators
- MySQL: DATEDIFF() und TIMESTAMPDIFF()
- SQLite: Date and Time Functions
- SQL Server: DATEDIFF
Beekeeper Studio ist eine kostenlose & quelloffene Datenbank-GUI
Das beste SQL-Abfrage- & Editor-Tool, das ich je benutzt habe. Es bietet alles, was ich zum Verwalten meiner Datenbank brauche. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio ist schnell, intuitiv und einfach zu bedienen. Beekeeper unterstützt jede Menge Datenbanken und läuft hervorragend auf Windows, Mac und Linux.
Was Nutzer über Beekeeper Studio sagen
„Beekeeper Studio hat meinen alten SQL-Workflow komplett ersetzt. Es ist schnell, intuitiv und macht die Arbeit mit Datenbanken wieder richtig Spaß.“
„Ich habe viele Datenbank-GUIs ausprobiert, aber Beekeeper trifft genau die richtige Balance zwischen Funktionen und Einfachheit. Es funktioniert einfach.“