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;
Tato varianta nevyžaduje podvýběr, GREATEST
nebo GROUP BY
a vygeneruje pouze požadované řádky. Jednodušší, rychlejší. Je levnější UNION
jeden řádek.
-
Přidejte 6 dní k prvnímu dni v měsíci před
date_trunc('week', ...)
pro výpočet prvního pondělí v měsíci . -
Přidejte 1 měsíc a odečtěte 1 den před
date_trunc('week', ...)
abyste získali poslední pondělí v měsíci .
To lze pohodlně nacpat do jedinéhointerval
výraz:'1 month - 1 day'
-
UNION
(neUNION ALL
) první den v měsíci pro přidání, pokud již není zahrnut jako pondělí. -
Všimněte si, že
date
+interval
výsledkem jetimestamp
, což je zde optimum. Podrobné vysvětlení:
Automatizace
Začátek datové řady můžete zadat v CTE:
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;
Nebo jej zabalte do jednoduché funkce SQL pro pohodlí s opakovanými voláními:
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;
Volejte:
SELECT * FROM f_week_starts_this_month('2013-02-01');
Předali byste datum prvního dne v měsíci, ale funguje to pro libovolné datum. Vy první den a všechna pondělí následujícího měsíce.