问题
I need a function in PostgreSQL that accepts a date range and returns the dates inside the date range that are Mondays. Anybody have an idea how this could be done?
回答1:
The most efficient way should be to find the first Monday and generate a series in steps of 7 days:
CREATE OR REPLACE FUNCTION f_mondays(dr daterange)
RETURNS TABLE (day date) AS
$func$
SELECT generate_series(a + (8 - EXTRACT(ISODOW FROM a)::int) % 7
, z
, interval '7 days')::date
FROM (
SELECT CASE WHEN lower_inc(dr) THEN lower(dr) ELSE lower(dr) + 1 END AS a
, CASE WHEN upper_inc(dr) THEN upper(dr) ELSE upper(dr) - 1 END AS z
) sub
$func$ LANGUAGE sql;
The subquery extracts start (
a
) and end (z
) of the range, adjusted for inclusive and exclusive bounds with range functions.The expression
(8 - EXTRACT(ISODOW FROM a)::int) % 7
returns the number of days until the next monday.0
if it's Monday already. The manual about EXTRACT().generate_series() can iterate any given interval - 7 days in this case. The result is a
timestamp
, so we cast todate
.Only generates Mondays in the range, no
WHERE
clause needed.
Call:
SELECT day FROM f_mondays('[2014-04-14,2014-05-02)'::daterange);
Returns:
day
----------
2014-04-14
2014-04-21
2014-04-28
SQL Fiddle.
回答2:
create function f(dr daterange)
returns setof date as $$
select d::date
from generate_series(
lower(dr), upper(dr), interval '1 day'
) s (d)
where
extract(dow from d) = 1 and
d::date <@ dr;
;
$$ language sql;
select f(daterange('2014-01-01', '2014-01-20'));
f
------------
2014-01-06
2014-01-13
来源:https://stackoverflow.com/questions/23047091/get-dates-of-a-day-of-week-in-a-date-range