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éhointervalvý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+intervalvý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.