在特定条件下将生料制成串

时间:2019-01-24 20:30:25

标签: tsql

基于下面提供的代码,我需要实现所需的表: enter image description here

规则是:

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

在其他帖子中,我要求提供有关该任务的简化版本的帮助:每天分别产生错误链。最好的选择(以非常有效的方式工作)是STUFF + For XML Path。

我们可以将它用于更复杂的任务吗?还是应该使用游标来实现?

我会对此提出任何建议。

关于, 槟榔

DECLARE @table1 TABLE
(
    [Ticket] INT,
    [ErrorCode] CHAR(1),
    [Date] DATETIME
);

INSERT INTO @table1
VALUES
(1, 'A', '01.07.2018  10:00:00'),
(1, 'B', '01.07.2018  10:02:00'),
(1, 'C', '01.07.2018  10:08:00'),
(1, 'A', '01.07.2018  10:30:09'),
(1, 'B', '01.07.2018  10:50:00'),
(1, 'D', '01.07.2018  10:55:00'),
(1, 'D', '01.07.2018  15:55:00'),
(1, 'D', '02.07.2018  10:55:00'),
(2, 'A', '20.10.2018  15:00:00'),
(2, 'C', '20.10.2018  17:00:00'),
(2, 'C', '20.10.2018  17:07:00'),
(2, 'A', '21.10.2018  09:00:00');

1 个答案:

答案 0 :(得分:5)

一种选择是使用条件标志,然后通过窗口函数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
      ,LastDate = convert(date,max(Date) over (Partition By Ticket,Grp))
      ,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  cte1 A
 Order by Ticket,Grp

返回

enter image description here

  

修改-调整效果

通过将XML/STUFF迁移到最终/精简集,您可能会获得更高的性能。首先,字符串聚合是一个沉重的打击。我们只是减少了通话次数。

另一种选择是使用TEMP表而不是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

enter image description here

cte1生成

enter image description here

cte2生成 注意,Grp是Flag的运行总计

enter image description here