尝试这个:
with seq as
(
select tbl.*,
row_number() over(order by assign_id) rn -- naturalized the order
from tbl
),
grp as
(
select cr.*,
sum(case when cr.grp = pr.grp or pr.grp is null then 0 else 1 end)
over(order by cr.rn) gn
from seq cr -- current row
left join seq pr -- previous row
on pr.rn = cr.rn - 1
)
,run as
(
select grp.*,
sum(time) over(partition by gn order by rn) as run_tot
from grp
)
select
id, assign_id, grp, time,
case when max(rn) over(partition by gn) <> rn then
null
else
run_tot
end as run_total
from run r;
输出:
ID ASSIGN_ID GRP TIME RUN_TOTAL
11 1788 NC 6 (null)
11 1802 NC 1 7
11 2995 C 7 7
11 5496 NC 11 11
11 6077 C 2 (null)
11 6216 C 2 (null)
11 6226 C 4 8
11 6790 NC 5 5
现场测试:http ://www.sqlfiddle.com/#!4/faacc/1
这个怎么运作:
ID ASSIGN_ID GRP TIME RN GN
11 1788 NC 6 1 0
11 1802 NC 1 2 0
11 2995 C 7 3 1
11 5496 NC 11 4 2
11 6077 C 2 5 3
11 6216 C 2 6 3
11 6226 C 4 7 3
11 6790 NC 5 8 4
我们基本上需要为GN
一个连续的 grp 分配一个组号(列)。然后我们可以做一个由 GN 划分的运行总和
您可以在此处查看查询的进度:http ://www.sqlfiddle.com/#!4/faacc/1
每一步都建立在上一步的基础之上。只需向下滚动即可查看解决方案的进展情况
编辑
查询可以缩短,因为您的报告没有显示每行总计的运行,它只显示在最后一行,而不是sum(time) over(partition by gn order by rn) as run_tot
,我们可以这样做sum(time) over(partition by gn) as run_tot
,即我们删除order by rn
; 然后检测该行是否是最后一行,如果是则执行sum over
,否则显示null。
最终查询:
with seq as
(
select
tbl.*,
row_number() over(order by assign_id) rn -- naturalized the order
from tbl
),
grp as
(
select
cr.*,
sum(case when cr.grp = pr.grp or pr.grp is null then 0 else 1 end)
over(order by cr.rn) gn
from seq cr -- current row
left join seq pr -- previous row
on pr.rn = cr.rn - 1
)
select
grp.*,
case when max(rn) over(partition by gn) <> rn then -- if not last row
null
else -- if last row
sum(time) over(partition by gn)
end as running_total
from grp;
现场测试:http ://www.sqlfiddle.com/#!4/faacc/7
编辑
关于多个ID,例如6790:
ID ASSIGN_ID GRP TIME
11 1788 NC 6
11 1802 NC 1
11 2995 C 7
11 5496 NC 11
11 6077 C 2
11 6216 C 2
11 6226 C 4
11 6790 NC 5
12 6790 NC 1
12 6791 NC 3
12 6792 NC 1
12 6793 NC 4
12 6794 C 1
12 6795 C 6
12 6797 C 8
13 6793 C 1
13 6794 C 4
13 6795 C 3
有两个相似的 ASSIGN_ID,例如 6790,但它属于一个更大的组(在 ID 上,分别为 11 和 12),因此为了隔离这两个组,我们必须按 ID 对它们进行分区。
这是最终查询,请注意在评论中添加了此内容:http ://www.sqlfiddle.com/#!4/83789/2
with seq as
(
select tbl.*,
-- added this: partition by id
-- naturalized the order: rn
row_number() over(partition by id order by assign_id) rn
from tbl
)
,grp as
(
select cr.*,
-- added this: partition by cr.id
sum(case when cr.grp = pr.grp then 0 else 1 end)
over(partition by cr.id order by cr.rn) gn
from seq cr -- current row
left join seq pr -- previous row
on
pr.id = cr.id -- added this
and pr.rn = cr.rn - 1
)
select id, assign_id, grp, time,
-- added this: partition by id
case when max(rn) over(partition by id,gn) <> rn then
null
else
-- added this: partition by id
sum(time) over(partition by id,gn)
end as running_total
from grp
order by id, rn;
输出:
ID ASSIGN_ID GRP TIME RUNNING_TOTAL
11 1788 NC 6 (null)
11 1802 NC 1 7
11 2995 C 7 7
11 5496 NC 11 11
11 6077 C 2 (null)
11 6216 C 2 (null)
11 6226 C 4 8
11 6790 NC 5 5
12 6790 NC 1 (null)
12 6791 NC 3 (null)
12 6792 NC 1 (null)
12 6793 NC 4 9
12 6794 C 1 (null)
12 6795 C 6 (null)
12 6797 C 8 15
13 6793 C 1 (null)
13 6794 C 4 (null)
13 6795 C 3 8
这是如何工作的,请注意ID 和 GN:
ID ASSIGN_ID GRP TIME RN GN RUNNING_TOTAL
11 1788 NC 6 1 1 (null)
11 1802 NC 1 2 1 7
11 2995 C 7 3 2 7
11 5496 NC 11 4 3 11
11 6077 C 2 5 4 (null)
11 6216 C 2 6 4 (null)
11 6226 C 4 7 4 8
11 6790 NC 5 8 5 5
12 6790 NC 1 1 1 (null)
12 6791 NC 3 2 1 (null)
12 6792 NC 1 3 1 (null)
12 6793 NC 4 4 1 9
12 6794 C 1 5 2 (null)
12 6795 C 6 6 2 (null)
12 6797 C 8 7 2 15
13 6793 C 1 1 1 (null)
13 6794 C 4 2 1 (null)
13 6795 C 3 3 1 8
在此处查看查询进度:http ://www.sqlfiddle.com/#!4/83789/2
更新尝试使用这个,它更简洁易读:https ://stackoverflow.com/a/10629498