Sql 对具有条件的前几行求和

Sql 对具有条件的前几行求和,sql,oracle,Sql,Oracle,我试图对一列求和,在有序列上提供了一个不太直接的条件 请参见以下示例了解我正在尝试的操作: 这就是我目前拥有的 -------------------------------------------------- ID | Month | Days -----------> ID | Month | Days_Cumulative -------------------------------------------------- AB | 2012/01 | 22 ----

我试图对一列求和,在有序列上提供了一个不太直接的条件

请参见以下示例了解我正在尝试的操作:

这就是我目前拥有的

--------------------------------------------------
 ID | Month | Days -----------> ID | Month | Days_Cumulative     
--------------------------------------------------
 AB | 2012/01 | 22 -----------> AB | 2012/01 | 22
--------------------------------------------------
 AB | 2012/02 | 23 -----------> AB | 2012/02 | 45
--------------------------------------------------
 AB | 2012/03 | 28 -----------> AB | 2012/03 | 73
--------------------------------------------------
 AB | 2013/07 | 11 -----------> AB | 2013/07 | 11
--------------------------------------------------
 AB | 2013/08 | 15 -----------> AB | 2013/08 | 99
--------------------------------------------------
这就是我希望实现的

--------------------------------------------------
 ID | Month | Days -----------> ID | Month | Days_Cumulative     
--------------------------------------------------
 AB | 2012/01 | 22 -----------> AB | 2012/01 | 22
--------------------------------------------------
 AB | 2012/02 | 23 -----------> AB | 2012/02 | 45
--------------------------------------------------
 AB | 2012/03 | 28 -----------> AB | 2012/03 | 73
--------------------------------------------------
 AB | 2013/07 | 11 -----------> AB | 2013/07 | 11
--------------------------------------------------
 AB | 2013/08 | 15 -----------> AB | 2013/08 | 26
--------------------------------------------------
第一个表中“Days_Cumulative”列的最后一行是99,应该是26,因为我只尝试对连续几个月的天数求和(我的逻辑当前对特定ID的所有行求和)。现在,我知道为什么我的查询会给出结果,但是,我不知道的是如何得到我想要的。基本上,我想要

 Sum(T1.DAYS) over(partition by T1.ID order by T1.Month)
一个新的连续月份开始后,重新开始求和。我的查询可能有点混乱——只要我两次加入我的源表——但我只是一步一步地工作,找不到解决我特定问题的方法

我的问题是:

WITH SRC AS
(Select ID, Month, Days 
, ROW_NUMBER() over(partition by ID order by Month) RN
from TABLE)
Select T1.ID, T1.Month, T1.Days
, CASE WHEN MONTHS_BETWEEN(T1.Month, T2.Month) > 1 THEN T1.DAYS
ELSE Sum(T1.DAYS) over(partition by T1.ID order by T1.Month) END AS Days_Cumulative
from SRC T1
Left Join SRC T2
On T1.ID = T2.ID
and T1.RN = T2.RN - 1 
Left Join SRC T3
On T1.ID = T3.ID
and T1.RN = T3.RN + 1 

任何洞察都会有帮助。

您需要定义连续月份的周期。有几种方法可以做到这一点。我会使用
行编号()来实现差异:


请注意,您的查询和示例数据非常不同。上面从结构上说明了应该做什么。您必须根据实际表格对其进行调整。

您可以基于连续性创建组,然后在组中查找累积和:

with cte
as (
    select ID,
        Month,
        Days,
        case 
            when to_date(month, 'yyyy/mm') 
            = lag(add_months(to_date(month, 'yyyy/mm'), 1)) 
                    over (order by Month) 
            then 0 else 1 end x
    from table
    )
select
    t.*,
    sum(Days) over (partition by grp order by month)
from (
    select
        t.*,
        sum(x) over (order by Month) grp
    from src t
) t;

试过这个,效果很好。感谢您的快速反馈!两个建议:(1)尝试
选择日期('2014/10','yyyy/mm')
看看会发生什么(如果您不理解,请阅读文档);(2) 研究Gordon更有效的解决方案-他使用的技巧是“禁忌法”的变体,用于解决缺口和孤岛问题。哦-我刚刚注意到:你有一个“评论”要求OP将你的解决方案标记为“正确”答案,然后当他这样做时,你删除了它?所以你必须知道这不完全符合道德?(否则为什么要删除它?)是否确实要继续此讨论?如果只是为了帮助海报,为什么在他们这样做之后,你要删除要求OP将你的答案标记为正确的评论?你的“温柔提醒”将来不会帮助其他新成员吗?这是多年前关于这一点的一些讨论:在这种情况下,请记住Gordon的答案实际上是优越的(OP似乎是自己得出的结论)——Tabibitosan方法比“组的开始”方法需要更少的子查询。@mathguy-你一如既往地绝对正确。从现在起,我不会要求任何人接受任何答案。一如既往地感谢您的反馈。不过,“乞讨选票”有点过分了。
with cte
as (
    select ID,
        Month,
        Days,
        case 
            when to_date(month, 'yyyy/mm') 
            = lag(add_months(to_date(month, 'yyyy/mm'), 1)) 
                    over (order by Month) 
            then 0 else 1 end x
    from table
    )
select
    t.*,
    sum(Days) over (partition by grp order by month)
from (
    select
        t.*,
        sum(x) over (order by Month) grp
    from src t
) t;