SELECT generate_series(date_trunc('week', date '2013-02-01' + interval '6 days')
, date_trunc('week', date '2013-02-01' + interval '1 month - 1 day')
, interval '1 week')::date AS day
UNION SELECT date '2013-02-01'
ORDER BY 1;
Diese Variante benötigt keine Unterauswahl, GREATEST
oder GROUP BY
und generiert nur die erforderlichen Zeilen. Einfacher, schneller. Es ist billiger zu UNION
eine Zeile.
-
Fügen Sie dem ersten Tag des Monats 6 Tage hinzu vor
date_trunc('week', ...)
um den ersten Montag des Monats zu berechnen . -
Addieren Sie 1 Monat und subtrahieren Sie 1 Tag vor
date_trunc('week', ...)
um den letzten Montag des Monats zu erhalten .
Dies kann bequem in ein einzigesinterval
gepackt werden Ausdruck:'1 month - 1 day'
-
UNION
(nichtUNION ALL
) der erste Tag des Monats, um ihn hinzuzufügen, es sei denn, er ist bereits als Montag enthalten. -
Beachten Sie das
date
+interval
ergibttimestamp
, was hier das Optimum ist. Ausführliche Erklärung:
Automatisierung
Sie können den Beginn der Datumsreihe in einem CTE angeben:
WITH t(d) AS (SELECT date '2013-02-01') -- enter 1st of month once
SELECT generate_series(date_trunc('week', d + interval '6 days')
, date_trunc('week', d + interval '1 month - 1 day')
, interval '1 week')::date AS day
FROM t
UNION SELECT d FROM t
ORDER BY 1;
Oder packen Sie es in eine einfache SQL-Funktion, um es mit wiederholten Aufrufen zu vereinfachen:
CREATE OR REPLACE FUNCTION f_week_starts_this_month(date)
RETURNS SETOF date AS
$func$
SELECT generate_series(date_trunc('week', $1 + interval '6 days')
, date_trunc('week', $1 + interval '1 month - 1 day')
, interval '1 week')::date AS day
UNION
SELECT $1
ORDER BY 1
$func$ LANGUAGE sql IMMUTABLE;
Aufruf:
SELECT * FROM f_week_starts_this_month('2013-02-01');
Sie würden das Datum für den ersten Tag des Monats übergeben, aber es funktioniert für alle Datum. Sie den ersten Tag und alle Montage für den folgenden Monat.