1

考虑我有下表:

entry       exit
2017-05-12  2017-05-15
2017-05-19  2017-05-19
2017-05-21  2017-06-25
2017-06-29  2017-07-22

使用 SQL,我想将其分解为行,其中每一行代表一天以及这一天是否在任何范围内。例如:

day        is_inside
2017-05-12 true
2017-05-13 true
2017-05-14 true
2017-05-15 true
2017-05-16 false
2017-05-17 false
2017-05-18 false
2017-05-19 true
2017-05-20 false
2017-05-21 true
...

您可以认为范围不重叠。

4

3 回答 3

2

您可以使用generate_series生成指定开始和结束期间之间的日期。然后可以将表left join编辑到此以生成所需的结果。

select t.dt,tbl.entry is null as is_inside
from generate_series('2018-05-12'::date,'2018-05-19','1 day') t(dt) --change the date range as needed
left join tbl on t.dt>=tbl.entry and t.dt<=tbl.exit
于 2018-09-12T02:03:10.880 回答
0

您可以使用generate_series(). 假设期间不重叠:

select gs.dte, (t.entry is not null) as is_inside
from (select generate_series(min_entry, max_exit, interval '1 day) gs(dte)
      from (select min(entry) as min_entry, max(exit) as max_exit
            from t
           ) t
     ) gs left join
     t
     on gs.dte >= t.entry and gs.dte <= t.exit;

两个注意事项:

  • 在更新的 Postgres 版本中,我会使用横向连接而不是子查询generate_series()
  • 如果确实有重叠,请使用existsinselect而不是left join.
于 2018-09-12T11:04:44.990 回答
0

这假设您有一个日期表(日期的计数表)。如果不这样做,请搜索日期表并创建一个。它基本上是一个表格,每个日期都有一行,它让您可以轻松地对日期范围进行查询。很多日期表有很多其他列,但为此您只需要日期列。如果需要,您可以创建一个临时日期表来运行查询。示例搜索结果

然后,您可以查询该表以获取您关心的日期范围,并尝试将外部联接保留到日期范围表 - 如果您获得联接,则为真,否则为假。像这样的东西(这可能不是确切的 postgres 语法,我对它生疏了,但理论是一样的)

Select DT.Date, CASE WHEN DR.entry IS NULL THEN 'true' else 'false' end as is_inside
From DateTable DT 
    left outer join DateRange DR on DT.Date between DR.entry and DR.exit
Where DT.Date  ... (date range to report)

如果您确实可能有重叠的范围,那么您需要做的就是区分结果 - 您只会得到一个错误或(一个或多个)真实结果。

于 2018-09-12T01:57:52.070 回答