PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Generieren Sie eine Reihe von Wochenintervallen für einen bestimmten Monat

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 einziges interval gepackt werden Ausdruck:'1 month - 1 day'

  • UNION (nicht UNION ALL ) der erste Tag des Monats, um ihn hinzuzufügen, es sei denn, er ist bereits als Montag enthalten.

  • Beachten Sie das date + interval ergibt timestamp , 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.