【问题标题】:Split overlapping intervals into smaller, touching ones in PostgreSQL在 PostgreSQL 中将重叠的间隔分割成更小的、接触的间隔
【发布时间】:2020-10-30 12:25:01
【问题描述】:

我需要有关查询的帮助,该查询应按以下方式拆分一些重叠的日期间隔。

例如,如果我们有一个下表

----------------------------------------------------------------------
|   column_name    |    value    |    start_date    |    end_date    |
----------------------------------------------------------------------
|     column1      |    value1   |    03-09-2020    |   26-09-2020   |
----------------------------------------------------------------------
|     column1      |    value2   |    07-09-2020    |   20-09-2020   |
----------------------------------------------------------------------

我想出一个查询来生成以下输出时遇到问题:

----------------------------------------------------------------------
|   column_name    |    value    |    start_date    |    end_date    |
----------------------------------------------------------------------
|     column1      |    value1   |    03-09-2020    |   07-09-2020   |
----------------------------------------------------------------------
|     column1      |    value2   |    07-09-2020    |   20-09-2020   |
----------------------------------------------------------------------
|     column1      |    value1   |    20-09-2020    |   26-09-2020   |
----------------------------------------------------------------------

【问题讨论】:

  • 您如何确定优先级?基于 column_name 还是 value?
  • 所以当我从第一个表中得到结果时,这意味着 ,,column1,, 有 ,,value1,, 从 03-09-2020 到 07-09-2020。然后值从 07-09-2020 切换到 value2,直到 20-09-2020 切换回 value1 到 2020 年 9 月 26 日。我意识到我是个错误。 Column2 应该是 Column1。

标签: sql postgresql


【解决方案1】:

一种方法是获取所有日期并使用横向连接来计算该日期的值:

with dates as (
      select start_date as date
      from t
      union 
      select end_date
      from t
     )
select tt.value, d.date as start_date, lead(d.date) over (order by d.date) as end_date
from dates d left join lateral
     (select t.*
      from t
      where start_date <= d.date and
            end_date > d.date
      order by start_date desc  -- this gets the most recent overlapping value
      limit 1
     ) tt
     on true
order by d.date;

Here 是一个 dbfiddle。

请注意,这会添加一个带有最终“无价值”期间的额外行。如果您不想要它,您可以轻松地将其过滤掉。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2019-09-14
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    相关资源
    最近更新 更多