Der*_*r U 2 sql t-sql sql-server sql-server-2012
尝试构建查询。
输入按“rn”列中的行号排序,“name”中的每个唯一值从 1 开始,并在“act”中定义给定的条目序列。在“act”列中,它在多次出现时保存两个值,>sleep< 和>wake<。目标是为这些值之一的每个连续行集找到 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
Run Code Online (Sandbox Code Playgroud)
所需的输出:
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
Run Code Online (Sandbox Code Playgroud)
输入源不提供更多列。每个子集中的成员数量可能比本例中的要多得多。
我尝试了不同的聚合方法,但没有成功。我相信使用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)
Run Code Online (Sandbox Code Playgroud)
您想要找到相似行的连续组,然后进行聚合。我喜欢行号方法的差异:
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;
Run Code Online (Sandbox Code Playgroud)
您可以通过查看子查询的作用来了解其工作原理。