Alle BeiträgeDas PerSight-Team · Zuletzt aktualisiert: 23. Juli 2026 · 8 Min. Lesezeit

In SQL nach Datumsbereich filtern (samt der BETWEEN-Falle)

Dieser Monat, die letzten 30 Tage, letztes Quartal: der sichere Weg, einen Datumsbereich in SQL abzufragen. Warum BETWEEN mit Uhrzeiten in die Irre führt, und die Entsprechungen in PostgreSQL, SQL Server, MySQL und Oracle.

"Bestellungen diesen Monat", "die letzten 30 Tage", "der Umsatz des letzten Quartals". Fast jeder Bericht beginnt mit einem Datumsbereich. Klingt trivial, doch wenn Ihre Datumsspalte auch eine Uhrzeit speichert, versteckt sich genau hier der häufigste Fehler. Sehen wir uns zuerst das sichere Muster an, dann die Funktionen der vier Datenbanken.

Warum sollte ich BETWEEN vermeiden?

Viele schreiben für "Januar" BETWEEN '2026-01-01' AND '2026-01-31'. Ist die Spalte ein reines Datum, ist das in Ordnung. Ist die Spalte aber ein Zeitstempel, fällt eine Bestellung vom 31. Januar um 09:00 Uhr aus der Grenze 2026-01-31 00:00:00 heraus und verschwindet stillschweigend. Weil BETWEEN beide Enden einschließt, kann diese Falle monatelang unbemerkt laufen.

Das sichere Muster ist das "halboffene Intervall": Anfang einschließen, Ende ausschließen. Vom Ersten des Monats bis zum Ersten des Folgemonats, letzteren ausgeschlossen:

SELECT *
FROM bestellungen
WHERE bestelldatum >= DATE '2026-01-01'
  AND bestelldatum <  DATE '2026-02-01';
Korrekt, ob mit oder ohne gespeicherte Uhrzeit; dieses Muster ist vorzuziehen. SQL Server kennt das DATE-Literal nicht; schreiben Sie das Datum dort als einfachen String (2026-01-01).

Wie schreibe ich "die letzten 30 Tage"?

Wollen Sie einen Bereich relativ zu "heute" statt zu einem festen Datum, kommen die "heute"- und "Tage abziehen"-Funktionen jeder Datenbank ins Spiel. Dieselbe Abfrage in vier Dialekten:

-- PostgreSQL
WHERE bestelldatum >= CURRENT_DATE - INTERVAL '30 days'

-- SQL Server
WHERE bestelldatum >= DATEADD(DAY, -30, CAST(GETDATE() AS date))

-- MySQL
WHERE bestelldatum >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)

-- Oracle
WHERE bestelldatum >= TRUNC(SYSDATE) - 30
Gleiche Logik, vier Dialekte.

Laufende Zeiträume wie dieser Monat oder dieses Jahr

Um den ersten Tag des laufenden Monats zu bekommen, ist date_trunc in PostgreSQL praktisch; für die Obergrenze addieren Sie einen Monat:

-- PostgreSQL: der laufende Monat
WHERE bestelldatum >= date_trunc('month', CURRENT_DATE)
  AND bestelldatum <  date_trunc('month', CURRENT_DATE) + INTERVAL '1 month';

SQL Server liefert den letzten Tag mit EOMONTH; MySQL hat LAST_DAY. Am robustesten ist es dennoch, den Ersten des Folgemonats als ausschließende Grenze zu verwenden, statt den letzten Tag einzuschließen; so bringt Sie die Uhrzeit nie durcheinander.

Wie erwischt mich die Zeitzone?

Speichert die Spalte UTC, meinen Sie aber "heute" in Ortszeit, können Datensätze nahe Mitternacht um einen Tag verrutschen. Achten Sie als Regel darauf, dass beim Berechnen des Bereichs Grenzen und Spalte in derselben Zeitzone liegen. Dieses Detail ist der Hauptverdächtige hinter "Warum sind die Zahlen einen Tag zu spät?" bei täglichen Dashboards.

Häufig gestellte Fragen

Sollte BETWEEN bei Datumsbereichen nie verwendet werden?
Speichert die Spalte ein reines Datum (ohne Uhrzeit), ist BETWEEN sicher und lesbar. Ist die Spalte ein Zeitstempel/Datetime, bevorzugen Sie das Muster ">= Anfang AND < nächster Tag"; dass BETWEEN die Obergrenze einschließt, verursacht dort stillen Datenverlust.
Kann ich Datumswerte als Text vergleichen?
Nicht empfehlenswert. Ein Datum gegen einen String wie '2026-01-01' zu vergleichen, verlässt sich auf die Formatübereinstimmung und erschwert die Nutzung eines Index. In einen Datumstyp umzuwandeln (DATE, CAST, TO_DATE) und als Datum zu vergleichen ist korrekt und schnell.
Brauche ich beim Gruppieren nach Jahr oder Monat noch einen Bereichsfilter?
Meist ja. Sie filtern den Bereich zuerst mit WHERE und aggregieren dann mit GROUP BY nach Jahr/Monat. Die ganze Tabelle ohne Bereichsfilter zu gruppieren ist langsam und zieht Zeiträume herein, die Sie nicht wollten.
Wie berechne ich Zeiträume wie "letztes Quartal"?
Sie ermitteln Anfang und Ende des Quartals und übergeben sie wieder als halboffenes Intervall. In PostgreSQL erleichtert date_trunc('quarter', ...) das; bei anderen Datenbanken berechnen Sie den ersten Monat des Quartals selbst.

Wenn Sie sich nicht merken wollen, welche Datumsfunktion zu welcher Datenbank gehört, sagen Sie PerSight einfach "Bestellungen dieses Monats" oder "Umsatz pro Tag der letzten 30 Tage." Es baut die Abfrage, die zu Ihrer gerade verbundenen Datenbank passt.

Quellen