一旦您有某种方式对行进行排序(在这里,我已经添加ord
),您就可以让 SQL Server 进行所需的累积:
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 次之,以此类推。
上述查询使用两个公用表表达式(CTE)。在第一个 ( Merged
) 中,我们递归地定义一个。查询的第一部分查找前面没有同一说话人的行的行(因此,从逻辑上讲,这些是说话人的每个完整语音部分的第一行)。
在递归部分,如果它属于同一个说话者,我们添加下一行,并且我们跟踪(in last
)我们最后添加的行。这个递归部分根据需要运行多次以累积完整的部分。
不幸的是,Merged
生成的集合还包括我们在构建不间断语音时采取的所有中间步骤。因此,在 中Final
,分配一个ROW_NUMBER()
允许我们轻松找到每一行的最后一个输出,该输出是由 生成的初始集合的一部分Merged
。所以最后的查询只选择那些行。
如果您没有像ord
上面那样方便的列(单调递增),您可以简单地使用另一个 CTE 生成这样的列,并且您所拥有的任何列都可以唯一地对行 (*) 进行排序。因此,如果您可以通过名为 的列唯一标识行time
,则可以将此 CTE 作为第一个:
;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