我不知道从哪里开始解决这个问题。我需要更新一个仅在每个月的第3个星期一的记录。在Postgres中我可以查询每个第二个或第三个星期一,或者在第n周的第n天更抽象一点吗?
我正在寻找Postgresql的优雅答案。现在我有这样粗糙的东西:
select d from generate_series(date_trunc('week',timestamp '2015-02-01' + interval '13 days'), timestamp '2015-02-01' + interval '1 month -1 day', interval '14 days') d;
答案 0 :(得分:1)
我喜欢使用日历表来查询这样的查询。
要选择2015年每个月的第三个星期一,我可以查询这样的日历表。
select cal_date
from calendar
where year_of_date = 2015
and day_of_week = 'Mon'
and day_of_week_ordinal = 3
order by cal_date;
cal_date -- 2015-01-19 2015-02-16 2015-03-16 2015-04-20 2015-05-18 2015-06-15 2015-07-20 2015-08-17 2015-09-21 2015-10-19 2015-11-16 2015-12-21
创建日历表的代码。 (这是pgAdminIII通过其CREATE SCRIPT菜单选择呈现的方式。)
CREATE TABLE calendar
(
cal_date date NOT NULL,
year_of_date integer NOT NULL,
month_of_year integer NOT NULL,
day_of_month integer NOT NULL,
day_of_week character(3) NOT NULL,
day_of_week_ordinal integer NOT NULL,
iso_year integer NOT NULL,
iso_week integer NOT NULL,
cal_quarter integer,
CONSTRAINT calendar_pkey PRIMARY KEY (cal_date),
CONSTRAINT cal_quarter_check CHECK (cal_quarter =
CASE
WHEN date_part('month'::text, cal_date) >= 1::double precision AND date_part('month'::text, cal_date) <= 3::double precision THEN 1
WHEN date_part('month'::text, cal_date) >= 4::double precision AND date_part('month'::text, cal_date) <= 6::double precision THEN 2
WHEN date_part('month'::text, cal_date) >= 7::double precision AND date_part('month'::text, cal_date) <= 9::double precision THEN 3
WHEN date_part('month'::text, cal_date) >= 10::double precision AND date_part('month'::text, cal_date) <= 12::double precision THEN 4
ELSE NULL::integer
END),
CONSTRAINT cal_quarter_range CHECK (cal_quarter >= 1 AND cal_quarter <= 4),
CONSTRAINT calendar_check CHECK (year_of_date::double precision = date_part('year'::text, cal_date)),
CONSTRAINT calendar_check1 CHECK (month_of_year::double precision = date_part('month'::text, cal_date)),
CONSTRAINT calendar_check2 CHECK (day_of_month::double precision = date_part('day'::text, cal_date)),
CONSTRAINT calendar_check3 CHECK (day_of_week::text =
CASE
WHEN date_part('dow'::text, cal_date) = 0::double precision THEN 'Sun'::text
WHEN date_part('dow'::text, cal_date) = 1::double precision THEN 'Mon'::text
WHEN date_part('dow'::text, cal_date) = 2::double precision THEN 'Tue'::text
WHEN date_part('dow'::text, cal_date) = 3::double precision THEN 'Wed'::text
WHEN date_part('dow'::text, cal_date) = 4::double precision THEN 'Thu'::text
WHEN date_part('dow'::text, cal_date) = 5::double precision THEN 'Fri'::text
WHEN date_part('dow'::text, cal_date) = 6::double precision THEN 'Sat'::text
ELSE NULL::text
END),
CONSTRAINT calendar_check4 CHECK (day_of_week_ordinal =
CASE
WHEN day_of_month >= 1 AND day_of_month <= 7 THEN 1
WHEN day_of_month >= 8 AND day_of_month <= 14 THEN 2
WHEN day_of_month >= 15 AND day_of_month <= 21 THEN 3
WHEN day_of_month >= 22 AND day_of_month <= 28 THEN 4
ELSE 5
END),
CONSTRAINT calendar_check5 CHECK (iso_year::double precision = date_part('isoyear'::text, cal_date)),
CONSTRAINT calendar_check6 CHECK (iso_week::double precision = date_part('week'::text, cal_date))
)
WITH (
OIDS=FALSE
);
您还需要
答案 1 :(得分:0)
也许试试这个:
SELECT *
, EXTRACT(DAY FROM gen)::int as dom -- DayOfMonth
, CEIL(EXTRACT(DAY FROM gen) / 7)::int as mow -- MonthOfWeek
from (
select generate_series(date_trunc('year', now()), date_trunc('year', now() + interval '1 year'), interval '1 day' )::date as gen
) as src
WHERE extract ('dow' from gen) = 1
AND CEIL(EXTRACT(DAY FROM gen) / 7)::int in (2,3)