根据参数 -Oracle 重新启动 sum(over) 函数

Posted

技术标签:

【中文标题】根据参数 -Oracle 重新启动 sum(over) 函数【英文标题】:Restarting sum(over) function based on parameter -Oracle 【发布时间】:2020-11-16 17:41:42 【问题描述】:

我试图做的是使用 sum over 函数,使其重置为 0 并在遇到参数值时重新开始。我附上的是一些带有开始和结束日期的基本会员数据。现在,如果会员期限之间的休息时间超过 5 天,则它会再次重新启动计数器。我尝试使用延迟函数,但 oracle 不允许窗口函数。

数据:

ID  BEG_DATE    END_DATE         MONTHS DAYS_IN_COVERAGE_BREAK  tot_membership_months   
123 01-JAN-15   31-DEC-15        30.3                          30.3 first term
123 01-JAN-16   28-FEB-17        35.3   1                      65.6 --Adds first & 2nd term
123 01-JUN-17   31-DEC-17        17.8   93                     17.8 **--restarts- lapse in coverage**
123 01-JAN-18   30-MAR-19        37.8   1                      55.6 --Adds from restart time

查询:

With TL as (select '123' as id, to_Date('01JAN2015') as Beg_date,to_date('31DEC2015') as end_Date from dual union
            select '123' as id, to_Date('01JAN2016') as Beg_date,to_date('28FEB2017') as end_Date from dual union
            select '123' as id, to_Date('01JUN2017') as Beg_date,to_date('31DEC2017') as end_Date from dual union
            select '123' as id, to_Date('01JAN2018') as Beg_date,to_date('30MAR2019') as end_Date from dual)
            
select TL.*, round((END_DATE-BEG_DATE) /12,1) as MONTHS,
            BEG_DATE-LAG(END_DATE) OVER (PARTITION BY ID ORDER BY BEG_DATE) as DAYS_IN_COVERAGE_BREAK
            --case when BEG_DATE-LAG(END_DATE) OVER (PARTITION BY ID ORDER BY BEG_DATE)<5
           -- then sum(round((END_DATE-BEG_DATE) /12,1) over (partition by mrn order by beg_date)) else round((END_DATE-BEG_DATE) /12,1) end as member_cum_months
from TL;

感谢任何见解。谢谢

【问题讨论】:

您的 Oracle 版本是多少?间隙和孤岛问题最有效的解决方案是 match_recognize 子句,但这仅在 Oracle 12.1 及更高版本中可用。 【参考方案1】:

这是一个间隙和岛屿问题,每行开始一个新的岛屿,与前一行有 5 天以上的差距。

这是一个使用窗口函数的选项:lag() 为我们提供了之前的 end_date,然后我们使用窗口总和,对于超过 5 天的每个间隔递增来定义组。

select id, beg_date, end_date, 
    end_date - min(beg_date) over(partition by id, grp order by beg_date) total_membership_days
from (
    select t.*,
        sum(case when beg_date > lag_end_date + interval '5' day then 1 else 0 end) over(partition by id order by beg_date) grp
    from (
        select t.*, 
            lag(end_date) over(partition by id order by beg_date) lag_end_date
        from tl t
    ) t
) t

如果您希望结果是几个月而不是几天,那么:

select id, beg_date, end_date, 
    months_between(end_date, min(beg_date) over(partition by id, grp order by beg_date)) total_membership_months
from (
    select t.*,
        sum(case when beg_date > lag_end_date + interval '5' day then 1 else 0 end) over(partition by id order by beg_date) grp
    from (
        select t.*, 
            lag(end_date) over(partition by id order by beg_date) lag_end_date
        from tl t
    ) t
) t 

【讨论】:

以上是关于根据参数 -Oracle 重新启动 sum(over) 函数的主要内容,如果未能解决你的问题,请参考以下文章

使用其他参数重新启动 Windows 服务

Python 3.6 sum() 是不是有 `start=0` 关键字参数? [复制]

使用 Docker-Desktop for Windows,如何配置 sysctl 参数以渗透重新启动?

函数助手选择__long Sum

vista下开机启动 简单绕过UAC的方法(自己使用runas参数重新启动自己,有点意思)

如何实现mongodb中的sum汇总操作?