Tsql 在特定条件下拉长为字符串

Tsql 在特定条件下拉长为字符串,tsql,Tsql,根据下面提供的代码,我需要实现所需的表格: 规则是: 对于每个股票代码器,仅当连续发生错误之间的时间差小于10分钟时,才返回正在生成群集的错误代码链/群集 在另一篇博文中,我请求有关该任务更简单版本的帮助:每天分别生成错误链。最好的选择(以非常有效的方式工作)是XML路径的STUFF+ 我们能用它来完成这个更复杂的任务吗?或者,它应该通过游标来实现 如果您能就此提出任何建议,我将不胜感激 问候,, 阿瑞克 一个选项是使用条件标志,然后通过窗口函数sum()对该标志进行聚合 示例 ;with c

根据下面提供的代码,我需要实现所需的表格:

规则是:

对于每个股票代码器,仅当连续发生错误之间的时间差小于10分钟时,才返回正在生成群集的错误代码链/群集

在另一篇博文中,我请求有关该任务更简单版本的帮助:每天分别生成错误链。最好的选择(以非常有效的方式工作)是XML路径的STUFF+

我们能用它来完成这个更复杂的任务吗?或者,它应该通过游标来实现

如果您能就此提出任何建议,我将不胜感激

问候,, 阿瑞克


一个选项是使用条件标志,然后通过窗口函数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是虚拟元素。请参见编辑-调整。如果不够,您可能需要创建临时表以提高性能。