WHERE条款

时间:2017-11-10 15:28:08

标签: postgresql

我可能会问错误的解决方案,但这是我知道如何表达我的问题的唯一方法。

我正在尝试创建一个包含每个月最后一天的行的视图。构造表的方式是使用开始日期和结束日期设置状态值。在任何给定的日子,表格中的对象将具有可能已经静态数月或可能在前一天更改的状态。仅在状态更改时才会创建新行。

因此,例如,如果我想要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

1 个答案:

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