我可能会问错误的解决方案,但这是我知道如何表达我的问题的唯一方法。
我正在尝试创建一个包含每个月最后一天的行的视图。构造表的方式是使用开始日期和结束日期设置状态值。在任何给定的日子,表格中的对象将具有可能已经静态数月或可能在前一天更改的状态。仅在状态更改时才会创建新行。
因此,例如,如果我想要2016-01-31上所有对象状态的快照,我会使用此查询:
select * from table
where '2016-01-31' between dtstart and dtend
我希望我的观点包括每个月的最后一天,从过去的日期到现在。我可以像这样创建这个范围:
select (d.d + '1 mon'::interval - '1 day'::interval)::date AS monthend
from generate_series('2016-01-01'::date::timestamp with time zone, now(), '1 mon'::interval) d(d)
我能想到实现这一目标的唯一方法是将日期列表传递给WHERE子句的LHS,但这似乎不可能。我确信我可以在psql中创建一个带有一些循环的表,但我对这种语言并不是很熟悉。
有什么建议吗?
表
unit | dtstart | dtend | status
---------------------------------------
01 | 2016-01-01 | 2016-05-30 | rented
02 | 2016-01-01 | 2016-03-14 | vacant
01 | 2016-06-01 | 2016-07-15 | vacant
01 | 2016-07-16 | 2016-07-31 | rented
02 | 2016-03-15 | 2016-04-15 | rented
02 | 2016-04-16 | 2016-12-31 | vacant
1月至6月的期望输出
date | unit | status
--------------------------
2016-01-31 | 01 | rented
2016-02-29 | 01 | rented
2016-03-31 | 01 | rented
2016-04-30 | 01 | rented
2016-05-31 | 01 | rented
2016-06-30 | 01 | vacant
2016-07-31 | 01 | rented
2016-01-31 | 02 | vacant
2016-02-29 | 02 | vacant
2016-03-31 | 02 | rented
2016-04-30 | 02 | vacant
2016-05-31 | 02 | vacant
2016-06-30 | 02 | vacant
解决方案:
select
ends.monthend,
us.*
from y_unit_status us
join (
select (d.d + '1 mon'::interval - '1 day'::interval)::date AS monthend
from generate_series('2016-01-01'::date::timestamp with time zone, now(), '1 mon'::interval) d(d)) ends
on ends.monthend between dtstart and dtend
答案 0 :(得分:0)
您可以加入两个查询:
SELECT t.*
FROM mytable t
JOIN (SELECT (d.d + '1 MON'::INTERVAL - '1 DAY'::INTERVAL)::DATE AS monthend
FROM GENERATE_SERIES('2016-01-01'::DATE::TIMESTAMP WITH TIME ZONE,
NOW(),
'1 MON'::INTERVAL) d(d)) ends
ON ends.monthend BETWEEN dtstart AND dtend