Tsql 在特定条件下拉长为字符串
根据下面提供的代码,我需要实现所需的表格: 规则是: 对于每个股票代码器,仅当连续发生错误之间的时间差小于10分钟时,才返回正在生成群集的错误代码链/群集 在另一篇博文中,我请求有关该任务更简单版本的帮助:每天分别生成错误链。最好的选择(以非常有效的方式工作)是XML路径的STUFF+ 我们能用它来完成这个更复杂的任务吗?或者,它应该通过游标来实现 如果您能就此提出任何建议,我将不胜感激 问候,, 阿瑞克Tsql 在特定条件下拉长为字符串,tsql,Tsql,根据下面提供的代码,我需要实现所需的表格: 规则是: 对于每个股票代码器,仅当连续发生错误之间的时间差小于10分钟时,才返回正在生成群集的错误代码链/群集 在另一篇博文中,我请求有关该任务更简单版本的帮助:每天分别生成错误链。最好的选择(以非常有效的方式工作)是XML路径的STUFF+ 我们能用它来完成这个更复杂的任务吗?或者,它应该通过游标来实现 如果您能就此提出任何建议,我将不胜感激 问候,, 阿瑞克 一个选项是使用条件标志,然后通过窗口函数sum()对该标志进行聚合 示例 ;with c
一个选项是使用条件标志,然后通过窗口函数sum()对该标志进行聚合 示例
;with cte as (
Select *
,Flg = case when datediff(MINUTE,lag(Date,1) over (Partition by Ticket Order By Date) , Date) > 10 then 1 else 0 end
From @table1
), cte1 as (
Select *
,Grp = sum(Flg) over (Partition By Ticket Order by Date)
From cte
)
Select Distinct
Grp
,Ticket
,Cluster = Stuff((Select '/' +ErrorCode From cte1 Where Ticket=A.Ticket and Grp=A.Grp For XML Path ('')),1,1,'')
From cte1 A
Order by Ticket,Grp
返回
Grp Ticket Cluster
0 1 A/B/C
1 1 A
2 1 B/D
3 1 D
4 1 D
0 2 A
1 2 C/C
2 2 A
编辑-请求的更新
;with cte as (
Select *
,Flg = case when datediff(MINUTE,lag(Date,1) over (Partition by Ticket Order By Date) , Date) > 10 then 1 else 0 end
From @table1
), cte1 as (
Select *
,Grp = sum(Flg) over (Partition By Ticket Order by Date)
From cte
)
Select Distinct
Grp
,Ticket
,Cluster = Stuff((Select '/' +ErrorCode From cte1 Where Ticket=A.Ticket and Grp=A.Grp For XML Path ('')),1,1,'')
From cte1 A
Order by Ticket,Grp
返回
Grp Ticket Cluster
0 1 A/B/C
1 1 A
2 1 B/D
3 1 D
4 1 D
0 2 A
1 2 C/C
2 2 A
编辑-调整性能
;with cte as (
Select *
,Flg = case when datediff(MINUTE,lag(Date,1) over (Partition by Ticket Order By Date) , Date) > 10 then 1 else 0 end
From @table1
), cte1 as (
Select *
,Grp = sum(Flg) over (Partition By Ticket Order by Date)
From cte
)
Select Distinct
Grp
,Ticket
,Cluster = Stuff((Select '/' +ErrorCode From cte1 Where Ticket=A.Ticket and Grp=A.Grp For XML Path ('')),1,1,'')
From cte1 A
Order by Ticket,Grp
通过将XML/STUFF
迁移到最终/简化集,您可能会获得更高的性能。字符串聚合从一开始就很受欢迎。我们只是在减少通话次数
另一种选择是使用临时表而不是CTE
;with cte as (
Select *
,Flg = case when datediff(MINUTE,lag(Date,1) over (Partition by Ticket Order By Date) , Date) > 10 then 1 else 0 end
From @table1
), cte1 as (
Select *
,Grp = sum(Flg) over (Partition By Ticket Order by Date)
From cte
), cte2 as (
Select Distinct
Grp
,Ticket
,LastDate = convert(date,max(Date) over (Partition By Ticket,Grp))
From cte1 A
)
Select *
,Times = Stuff((Select ',' +format(Date,'HH:mm') From cte1 Where Ticket=A.Ticket and Grp=A.Grp For XML Path ('')),1,1,'')
,Cluster = Stuff((Select '/' +ErrorCode From cte1 Where Ticket=A.Ticket and Grp=A.Grp For XML Path ('')),1,1,'')
From cte2 A
Order by Ticket,Grp
编辑-逐步进行
cte生成
请注意,Flg为1或0
cte1生成
cte2生成
请注意,Grp是标志的运行总数
如果输入中还有一条记录
(1,'X',2018-07-01 10:11:00')
,该怎么办?结果中是否有两行(1'A/B/C')
和(1'B/C/X')
,还是有一行(1'A/B/C/X')
或其他内容?附加记录X将添加到第一个字符串:1:A/B/C/X。只要两个后续记录之间的时间差小于10分钟,它就应该包含在同一个链中。超过10分钟的差异会断开链。嗨,John,效果非常好,谢谢!必须熟悉该标志的功能。如果另外两列非常方便,应该怎么做:1.column包含集群中最后一个错误代码的日期?2.字符串列中列出的错误的相关时间(仅hh:mm)?我将非常感谢您在这方面的帮助。@Arkadiuszcieselski请参阅更新。这将是非常值得你的时间来获得舒适的窗口功能。。。此外,如果您觉得答案有用,您也可以接受。@ArkadiuszCiesielski更新了很多次再次感谢您,代码的效率和优雅程度:)我这边的最后一个问题:您认为应该创建什么样的索引以及源表的哪些列来改进处理?现在,返回1k行的输出大约需要10分钟,这并不令人印象深刻。。我已经创建了非聚集的票证和日期,但它没有改变任何东西。@arkadiuszcieselski索引不会给你带来太多。标志和Grp是虚拟元素。请参见编辑-调整。如果不够,您可能需要创建临时表以提高性能。