仅查询特定的每月天数

时间:2015-03-17 01:00:03

标签: postgresql

我不知道从哪里开始解决这个问题。我需要更新一个仅在每个月的第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;

2 个答案:

答案 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
);

您还需要

  • GRANT和REVOKE声明 - 应该允许很少人更改此类表格的内容,
  • 合适的CREATE INDEX声明。

答案 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)