Differenz zwischen Daten in SQL: DATEDIFF und seine Entsprechungen
Zu zählen, wie viele Tage zwischen zwei Daten liegen, geht in jeder SQL-Datenbank — aber jedes DBMS macht es auf seine Weise. MySQL und SQL Server haben die Funktion DATEDIFF, aber mit unterschiedlichen Argumenten; PostgreSQL hat sie überhaupt nicht — dort werden Daten einfach subtrahiert. Die Übersicht:
Gehen wir jedes DBMS durch und lösen dann echte Aufgaben: von „wie lange hat der Kunde bis zur ersten Bestellung überlegt" bis zum Alter aus dem Geburtsdatum.
DATEDIFF in MySQL
Die MySQL-Version der Funktion nimmt zwei Daten und liefert die Differenz in Tagen. Das spätere Datum kommt zuerst:
MySQL 8.1SELECT DATEDIFF('2026-06-12', '2026-06-01') AS days;
Vertauscht man die Argumente, wird das Ergebnis negativ — eine häufige Fehlerquelle in Berichten:
MySQL 8.1SELECT DATEDIFF('2026-06-01', '2026-06-12') AS days; -- -11
Stunden, Monate und Jahre kann MySQLs DATEDIFF nicht zählen — dafür gibt es TIMESTAMPDIFF, dessen Argumentreihenfolge umgekehrt ist: erst der Anfang, dann das Ende:
MySQL 8.1SELECT TIMESTAMPDIFF(HOUR, '2026-06-11 10:00:00', '2026-06-12 18:30:00') AS hours; -- 32: TIMESTAMPDIFF liefert nur volle Stunden (32.5 wird abgeschnitten) SELECT TIMESTAMPDIFF(MONTH, '2026-01-15', '2026-06-12') AS months; -- 4: volle Monate zwischen den Daten
Was liefert SELECT DATEDIFF('2026-06-01', '2026-06-12') in MySQL?
DATEDIFF in SQL Server
In SQL Server hat die Funktion drei Argumente: Einheit, Anfang, Ende. Beachten Sie — die Daten stehen in umgekehrter Reihenfolge im Vergleich zu MySQL:
MySQL 8.1SELECT DATEDIFF(day, '2026-06-01', '2026-06-12') AS days; -- 11 SELECT DATEDIFF(hour, '2026-06-11 10:00:00', '2026-06-12 18:30:00') AS hours; -- 32
SQL Server hat eine tückische Eigenheit: Er zählt keine vollen Perioden, sondern die Anzahl überschrittener Einheitsgrenzen. Die Differenz „in Jahren" zwischen dem 31. Dezember und dem 1. Januar beträgt ein Jahr:
MySQL 8.1SELECT DATEDIFF(year, '2025-12-31', '2026-01-01') AS years; -- 1, obwohl nur ein Tag vergangen ist
Deshalb darf man DATEDIFF(year, ...) in SQL Server nicht direkt für Alter oder Betriebszugehörigkeit verwenden — das Ergebnis ist für alle, deren Geburtstag noch bevorsteht, um fast ein Jahr zu hoch.
PostgreSQL: Subtraktion statt DATEDIFF
Eine Abfrage mit DATEDIFF endet in PostgreSQL mit einem Fehler:
MySQL 8.1SELECT DATEDIFF('2026-06-12', '2026-06-01');
Statt einer Funktion gibt es hier Arithmetik: Die Differenz zweier DATE-Werte ist eine ganze Zahl von Tagen:
PostgreSQL 17.5SELECT DATE '2026-06-12' - DATE '2026-06-01' AS days;
Beim Typ TIMESTAMP liefert die Subtraktion keine Zahl, sondern ein Intervall:
PostgreSQL 17.5SELECT TIMESTAMP '2026-06-12 18:30:00' - TIMESTAMP '2026-06-11 10:00:00' AS diff; -- 1 day 08:30:00
Um ein Intervall in eine Zahl zu verwandeln, gibt es zwei Wege:
-
EXTRACT(EPOCH FROM ...) — rechnet das Intervall in Sekunden um, danach gewöhnliche Arithmetik:
PostgreSQL 17.5SELECT EXTRACT(EPOCH FROM (TIMESTAMP '2026-06-12 18:30:00' - TIMESTAMP '2026-06-11 10:00:00')) / 3600 AS hours; -- 32.5: anders als bei TIMESTAMPDIFF bleibt der Nachkommateil erhalten -
AGE(...) — liefert ein „menschliches" Intervall in Jahren, Monaten und Tagen:
PostgreSQL 17.5SELECT AGE(TIMESTAMP '2026-06-12', TIMESTAMP '1995-08-20') AS age; -- 30 years 9 mons 23 days
Warum schlägt SELECT DATEDIFF('2026-06-12', '2026-06-01') in PostgreSQL fehl?
Praxisbeispiel: von der Registrierung zur ersten Bestellung
Berechnen wir anhand der Lieferdienst-Datenbank, wie viele Tage zwischen der Registrierung eines Nutzers und seiner ersten Bestellung vergehen — eine klassische Produktmetrik:
Die MySQL-Variante:
MySQL 8.1SELECT u.user_id, DATE(u.registration_date) AS registered, DATE(MIN(o.order_date)) AS first_order, DATEDIFF(MIN(o.order_date), u.registration_date) AS days_to_order FROM users u JOIN orders o ON o.user_id = u.user_id GROUP BY u.user_id, u.registration_date ORDER BY u.user_id LIMIT 5;
Dieselbe Abfrage für PostgreSQL:
PostgreSQL 17.5SELECT u.user_id, DATE(u.registration_date) AS registered, DATE(MIN(o.order_date)) AS first_order, MIN(o.order_date)::date - u.registration_date::date AS days_to_order FROM users u JOIN orders o ON o.user_id = u.user_id GROUP BY u.user_id, u.registration_date ORDER BY u.user_id LIMIT 5;
Die Abfragen unterscheiden sich in einer einzigen Zeile — der Art, die Daten zu subtrahieren — und das Ergebnis ist identisch.
Alter aus dem Geburtsdatum
Noch eine Standardaufgabe, bei der man leicht danebenliegt. Die korrekten Varianten:
MySQL 8.1-- MySQL: TIMESTAMPDIFF zählt volle Jahre SELECT TIMESTAMPDIFF(YEAR, '1995-08-20', CURDATE()) AS age;
PostgreSQL 17.5-- PostgreSQL: AGE liefert ein Intervall, daraus die Jahre extrahieren SELECT date_part('year', AGE(DATE '1995-08-20')) AS age;
Beide liefern 30 für eine Person, die am 20. August 1995 geboren wurde (Stand 12. Juni 2026): Der Geburtstag steht noch aus, volle Jahre sind es 30. Das naive (aktuelles Jahr - Geburtsjahr) ergäbe 31 — bis zum Geburtstag eins zu viel. Beide Blöcke sind ausführbar — setzen Sie Ihr eigenes Geburtsdatum ein und prüfen Sie es.
Spickzettel: Aufgabe → Funktion
Und der wichtigste Unterschied zum Merken: MySQLs TIMESTAMPDIFF und PostgreSQLs AGE zählen volle Perioden, SQL Servers DATEDIFF dagegen Grenzüberschreitungen.
Wie weiter
- wie die Typen DATE, TIME und TIMESTAMP funktionieren — in der Lektion Datum und Zeit in SQL;
- Datumsfunktionen mit Übungen — in der Lektion Arbeiten mit Datum und Zeit;
- Kurzreferenzen — im Handbook: DATEDIFF, TIMESTAMPDIFF;
- an echten Aufgaben üben — im SQL-Trainer.
Passende Artikel
ROW_NUMBER vs RANK vs DENSE_RANK in SQL: der Unterschied an einem Beispiel
Drei Ranking-Funktionen, eine Abfrage — und der Unterschied ist sichtbar
COALESCE in SQL: Was es ist und wie es funktioniert — Beispiele | SQL Academy
Das erste Nicht-NULL-Argument, und warum NULLIF dazugehört
CTE in SQL: Was eine Common Table Expression (WITH) ist — Beispiele
Unterabfragen mit Namen, Schrittketten und Rekursion