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;