これを試して:
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
2つの類似したASSIGN_ID、たとえば6790がありますが、それはより大きなグループ(ID、11と12)に属しているため、これら2つのグループを分離するには、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