我有日期重叠的定价记录.很少有日期会有一个以上的重叠价格.请遵循以下示例:

例如,在2022/02/15,有两种价格10和8.

article price startdate enddate
123 10 2022/02/02 2049/12/31
123 8 2022/02/14 2022/09/14
123 5 2022/03/14 2022/04/06
123 4 2022/04/11 2022/04/27

我想对如下日期范围应用有效价格,避免输出中的价格冲突.

article price startdate enddate
123 10 2022/02/02 2022/02/13
123 8 2022/02/14 2022/03/13
123 5 2022/03/14 2022/04/06
123 8 2022/04/07 2022/04/10
123 4 2022/04/11 2022/04/27
123 8 2022/04/28 2022/09/14
123 10 2022/09/15 2049/12/31

我可以想出窗口函数来调整结束日期和价格,但我不能完全围绕这个问题来获得完整的解决方案.欢迎提出任何建议/解决方案.

数据库:snowflake

非常感谢.

推荐答案

使用新起始价格窗口的逻辑可以赢得重叠.

离散日期版本:

with data(article,price,startdate,enddate) as (
    select * FROM VALUES
        (123, 10, '2022-02-02'::date, '2049-12-31'::date),
        (123, 8,  '2022-02-14'::date, '2022-09-14'::date),
        (123, 5,  '2022-03-14'::date, '2022-04-06'::date),
        (123, 4,  '2022-04-11'::date, '2022-04-27'::date)
), dis_times as (
    select article,
        date as startdate,
        lead(date) over(partition by article order by date)-1 as enddate
    from (
        select distinct article, startdate as date from data
        union
        select distinct article, enddate+1 as date from data
    )
    qualify enddate is not null
)
select 
    d1.article, 
    d1.price, 
    d2.startdate,
    d2.enddate
from data as d1
join dis_times as d2
    on d1.article = d2.article 
        and d2.startdate between d1.startdate and d1.enddate qualify row_number() over (partition by d1.article, s_startdate order by d1.startdate desc) = 1
order by 1,3;

给予:

ARTICLE PRICE S_STARTDATE S_ENDDATE
123 10 2022-02-02 2022-02-13
123 8 2022-02-14 2022-03-13
123 5 2022-03-14 2022-04-06
123 8 2022-04-07 2022-04-10
123 4 2022-04-11 2022-04-27
123 8 2022-04-28 2022-09-14
123 10 2022-09-15 2049-12-31

连续时间戳版本:

with data(article,price,startdate,enddate) as (
    select * FROM VALUES
        (123, 10, '2022-02-02'::date, '2049-12-31'::date),
        (123, 8,  '2022-02-14'::date, '2022-09-14'::date),
        (123, 5,  '2022-03-14'::date, '2022-04-06'::date),
        (123, 4,  '2022-04-11'::date, '2022-04-27'::date)
), dis_times as (
    select article,
        date as startdate,
        lead(date) over(partition by article order by date) as enddate
    from (
        select distinct article, startdate as date from data
        union
        select distinct article, enddate as date from data
    )
    qualify enddate is not null
)
select 
    d1.article, 
    d1.price, 
    d2.startdate,
    d2.enddate
from data as d1
join dis_times as d2
    on d1.article = d2.article 
        and d2.startdate >= d1.startdate and d2.startdate < d1.enddate
qualify row_number() over (partition by d1.article, s_startdate order by d1.startdate desc) = 1
order by 1,3;

which 给予:

ARTICLE PRICE S_STARTDATE S_ENDDATE
123 10 2022-02-02 2022-02-14
123 8 2022-02-14 2022-03-14
123 5 2022-03-14 2022-04-06
123 8 2022-04-06 2022-04-11
123 4 2022-04-11 2022-04-27
123 8 2022-04-27 2022-09-14
123 10 2022-09-14 2049-12-31

感谢MatBailie提出的更紧密的加入建议.

join dis_times as d2
    on d1.article = d2.article 
        and d2.startdate between d1.startdate and d1.enddate 

这是我通常在这段时间内做的连续范围

and d2.startdate between d1.startdate and d1.enddate and d2.startdate < d1.enddate

而不是这个表格

and d2.startdate >= d1.startdate and d2.startdate < d1.enddate

因为根据我的经验,它表现得更好.总是测试你的复杂性.

Sql相关问答推荐

无法找到正确的SQL查询需求

Android房间fts4匹配语法AND OR

Ffltter&;Dart SQL Lite包:是否可以在一个查询中执行多条更新语句(每次执行不同的WHERE参数)

更新其组的日期字段值小于最大日期减go 天数的记录

在数据库中搜索列

PostgreSQL:按小时查看调整日期

SQL计数条目大于日期,包括交叉表中的零

插入具有预期逻辑的查询以Forking 表

将二维数组的第一个和第二个元素取消嵌套到两个一维数组中

SQL Server 查询 WHERE LIKE

给定 3 个键列,从一个表中 Select 另一表中不存在的所有数据

两个具有 NULL 值的表达式结果之间的差异

Postgresql 具有相似行为和模式行为的问题

Oracle SQL:通过将日期与另一个表行进行比较来 Select 值

基于字符串的SQL查询

我如何编写一个遍历数组数组并将所有值连接成一个字符串的 postgres 函数

有没有一种方法可以将始终遵循序列的单个字段的值组合起来,以创建每个 ID 的所有移动?

如何跨行合并以删除 SQL 中的空值?

在 PostgreSQL 中,如何将数组中的每个元素用作另一个表中的键?

如何列出 Oracle 数据库中的所有函数并按修改日期排序