行を並べ替える方法ができたら、SQL Serverに必要な累積を実行させます(ここに追加しましたord
)。
declare @t table (speaker int not null,duration int not null,ord int not null)
insert into @t (speaker,duration,ord) values
(1, 480,1),
(2, 100,2),
(2, 260,3),
(2, 200,4),
(1, 2640,5),
(2, 280,6)
;with Merged as (
select speaker,duration,ord,ord as last
from @t t1
where not exists(
select * from @t t2
where t1.speaker = t2.speaker and t1.ord = t2.ord + 1)
union all
select m.speaker,m.duration+t.duration,m.ord,t.ord
from Merged m
inner join @t t on m.speaker = t.speaker and m.last = t.ord - 1
), Final as (
select speaker,duration,ord,last,
ROW_NUMBER() OVER (PARTITION BY ord ORDER by last desc) as rn
from Merged
)
select * from Final where rn = 1 order by duration desc
結果:
speaker duration ord last rn
----------- ----------- ----------- ----------- --------------------
1 2640 5 5 1
2 560 2 4 1
1 480 1 1 1
2 280 6 6 1
したがって、スピーカー1のシングルデュレーションは2640で最も長く、スピーカー2は560で2番目になりました。
上記のクエリは、2つの共通テーブル式(CTE)を使用します。最初の(Merged
)では、再帰的に定義します。クエリの最初の部分は、同じ話者の直前の行がない行を検索します(したがって、論理的には、これらは話者の音声の途切れのない各セクションの最初の行です)。
last
再帰部分では、同じスピーカーに属している場合は次の行を追加し、最後に追加した行を追跡します。この再帰部分は、壊れていないセクションを蓄積するために必要な回数だけ実行されます。
残念ながら、Merged
生成されるセットには、中断のないスピーチを構築するために行ったすべての中間ステップも含まれています。したがって、でFinal
、を割り当てます。ROW_NUMBER()
これにより、によって生成された初期セットの一部であった各行の最後の出力を簡単に見つけることができますMerged
。したがって、最後のクエリはそれらの行を選択するだけです。
上記のように(単調に増加する)のような便利な列がない場合は、別のCTEを使用しord
てそのような列を生成するだけで、行を一意に並べ替える列(*)を使用できます。したがって、と呼ばれる列によって行を一意に識別できる場合は、このCTEを最初のCTEとして配置できます。time
;WITH StrictOrdered as (
SELECT speaker,duration,
ROW_NUMBER() OVER (ORDER BY time) as ord
FROM YourTable
)
@t
次に、クエリの残りの部分でのすべての使用を。に置き換えますStrictOrdered
。
(*更新された例time
はこの要件に適合しません)
各スピーカーの最高値を取得するには、次を置き換えます。
select * from Final where rn = 1 order by duration desc
と:
, Highest as (
select *,ROW_NUMBER() OVER (PARTITION BY Speaker ORDER BY duration desc) as rnDuration
from Final where rn = 1
)
select * from Highest where rnDuration = 1