尝试构建查询。
输入按“rn”列中的rownumber排序,以“name”中的每个唯一值开头,并在“act”中定义给定的条目序列。在列'act'中,它在多次出现时保持两个值,> sleep<和>唤醒<。目标是为其中一个值的每个连续行集找到startt和endd的最小值和最大值。
这应该是输入:
name act rn startt endd
---------- ---------- ------ ------ ------
jimmy sleep 1 1 3
jimmy wake 2 4 7
jimmy wake 3 8 10
jimmy sleep 4 11 13
karen wake 1 1 4
karen sleep 2 5 7
karen wake 3 8 9
karen wake 4 10 12
karen wake 5 13 14
karen sleep 6 15 17
karen sleep 7 18 20
所需的输出:
name act startt endd
---------- ---------- ------ ------
jimmy sleep 1 3
jimmy wake 4 10
jimmy sleep 11 13
karen wake 1 4
karen sleep 5 7
karen wake 8 14
karen sleep 15 20
输入源不提供更多列。在这个例子中,每个子集中的成员数量可以非常高。
我尝试了不同的聚合方式,但都没有效果。我相信使用LEAD
和LAGG
并且进一步的欺骗可能会让我在那里,但这看起来非常不优雅。我认为区分每个子集是关键,即创建一个对其所有成员唯一的标识符。有了这个,min
和max
的汇总很简单。也许我错了。也许这是不可能的。也许是自我加入。也许是一个递归的cte。我不知道。
所以:有人知道如何获得这个吗?非常感谢帮助。
更新
感谢Gordon Linoff,shawnt00和评论的其他贡献者。根据您的建议,我在逻辑关闭工具箱中感到很大的差距。
感兴趣的是:
declare @t table (
name nvarchar(10)
,act nvarchar (10)
,startt smallint
,endd smallint
)
insert into @t (
name
,act
,startt
,endd
)
values
('jimmy','sleep', 1,3)
,('jimmy','wake', 4,7)
,('jimmy','wake', 8,10)
,('jimmy','sleep', 11,13)
,('karen','wake', 1,4)
,('karen','sleep', 5,7)
,('karen','wake', 8,9)
,('karen','wake', 10,12)
,('karen','wake', 13,14)
,('karen','sleep', 15,17)
,('karen','sleep', 18,20)
; --- all rows, no aggregating
with
cte as (
select
name
,act
,row_number() over (partition by name order by name,startt) rn
,row_number() over (partition by name, act order by name,startt) act_n
,startt
,endd
from
@t )
select
name
,act
,startt
,endd
,rn
,act_n
,rn - act_n diff
from
cte
order by
name
,rn
;--- aggregating for the desired ouput
with
cte as (
select
name
,act
,row_number() over (partition by name order by name,startt) rn
,row_number() over (partition by name, act order by name,startt) act_n
,startt
,endd
from
@t )
select
name
,act
,min(startt) startt
,max(endd) endd
,min(rn) min_rn
,max(rn) max_rn
from
cte
group by
name
,act
,rn - act_n
order by
name
,min(rn)
答案 0 :(得分:3)
您希望找到相似行的连续组,然后进行聚合。我喜欢行数方法的不同之处:
select name, act, min(startt) as startt, max(endd) as endd
from (select i.*,
row_number() over (partition by name, act order by rn) as seqnum_na,
row_number() over (partition by name order by rn) as seqnum_n
from input i
) i
group by (seqnum_n - seqnum_na), name, act;
您可以通过查看子查询的作用来了解其工作原理。
答案 1 :(得分:1)
这假设您在rn
编号中没有任何空白,因此它不会再次计算。
with T2 as (
select *, row_number() over (partition by name, act order by rn) as grp_rn
from T
)
select name, act, min(startt) as startt, max(endd) as endd
from T2
group by name, act, rn - grp_rn
order by name, startt;
http://rextester.com/CCQJJ93990
这是一个典型的空白和岛屿查询。这里的关键是当你有一个行集群时,两个不同的编号将逐步增加,这意味着差异将是集群的常量。当您沿着列表工作时,这种差异会增加。