Generierung von Zeitreihen, die zwischen zwei Daten in PostgreSQL
Ich habe eine Abfrage wie diese, die schön ist, generiert eine Reihe von Daten, die zwischen 2 angegebenen Terminen:
select date '2004-03-07' + j - i as AllDate
from generate_series(0, extract(doy from date '2004-03-07')::int - 1) as i,
generate_series(0, extract(doy from date '2004-08-16')::int - 1) as j
Erzeugt es 162 Termine zwischen 2004-03-07
und 2004-08-16
und das, was ich will. Das problem bei diesem code ist, dass es nicht die richtige Antwort, wenn die beiden Termine sind aus verschiedenen Jahren, zum Beispiel, wenn ich versuche 2007-02-01
und 2008-04-01
.
Gibt es eine bessere Lösung?
InformationsquelleAutor der Frage f.ashouri | 2013-01-01
Du musst angemeldet sein, um einen Kommentar abzugeben.
Kann getan werden, ohne eine Konvertierung in/aus int - (aber an/aus timestamp statt)
InformationsquelleAutor der Antwort wildplasser
Können Sie generieren Serie direkt mit Termin. Keine Notwendigkeit für die Verwendung von ints oder Zeitstempel:
InformationsquelleAutor der Antwort fbonetti
Gibt es zwei Antworten (so weit). Beide arbeiten, aber beide sind suboptimal. Hier ist ein drittes:
Keine Notwendigkeit für eine zusätzliche
date_trunc()
. Der cast zudate
(day::date
) bedeutet, dass implizit.Aber es gibt auch keinen Punkt in der casting-Datums-Literale in
date
als input-parameter. Au contraire,timestamp
ist die beste Wahl hier. Der Vorteil in der Leistung klein ist, aber es gibt keinen Grund, es nicht zu nehmen. Und Sie nicht unnötig umfassen Sommerzeit-Regeln gepaart mit dem Datentyptimestamp with time zone
. Siehe Erklärung weiter unten.Kürzer, gleichwertig:
Oder sogar mit der set-returning Funktion in der
SELECT
Liste:Den
AS
Schlüsselwort ist erforderlich hier, da die Spalte aliasday
würde missverstanden werden sonst.Ich würde nicht raten, zu verwenden, die Letzte vor Postgres-10, zumindest nicht mit mehr als einem set-returning Funktion in der gleichen
SELECT
Liste. Siehe:Warum?
Gibt es eine Reihe von überladenen Varianten
generate_series()
. Derzeit (Postgres-10):Variante nehmen und die Rückkehr
numeric
wurde Hinzugefügt, mit Postgres 9.5. Aber das nur relevant, hier sind die letzten zwei Fett nehmen und die Rückkehrtimestamp
/timestamptz
.Wie Sie sehen können, gibt es keine Variante nehmen oder die Rückkehr
date
. Deshalb brauchen wir eine explizite cast, wenn wir zurückkehren wollendate
. Vorbeitimestamp
wird die right-Funktion direkt, ohne abzusteigen, in Funktion Typ Auflösung Regeln und ohne zusätzliche Besetzung für den input.Sowie
timestamp '2004-03-07'
ist vollkommen gültig. Der Zeit-Teil wird standardmäßig auf00:00
wenn Sie weggelassen werden.DankFunktion Typ Auflösung können wir passieren noch
date
. Aber das erfordert mehr Arbeit von Postgres. Es ist ein implizite cast vondate
zutimestamp
sowie vondate
zutimestamptz
. Wäre mehrdeutig, abertimestamptz
ist "bevorzugt" unter "Datum/Zeit-Typen". Also die match ist entschieden zu Schritt 4d.:Neben der zusätzlichen Arbeit in der Funktion Typ Auflösung dies fügt eine zusätzliche Besetzung zu
timestamptz
. Der cast zutimestamptz
bietet nicht nur mehr Kosten, es kann auch zu Problemen führen, mit daylight saving time (DST), was zu unerwarteten Ergebnissen in seltenen Fällen. (DST ist ein Schwachsinniger Begriff, btw, kann dies nicht genug betonen.) Related:Fügte ich demos auf der Geige zu zeigen, die teurer query plan:
dbfiddle hier
Verwandte:
InformationsquelleAutor der Antwort Erwin Brandstetter