MSSQL TSQL挑战连续时间线分组

时间:2016-07-21 05:00:33

标签: sql-server tsql analytics partitioning timeline

我想在图像中实现以下结果。在MSSQL中将连续范围折叠为单行。下面的示例代码,我几乎已经开始工作,虽然我认为它是相当新秀。我想我的意思是使用超前/滞后和分区,但不知道如何使其工作。

示例结果

Example Result

样本表数据....

DROP Table #t2
SELECT 
    [Duration (hours)]
    ,CAST(LTRIM(RTRIM([Event Start])) AS DATETIME) AS [Start_Date]
    ,CAST(LTRIM(RTRIM([Event Finsh])) AS DATETIME) AS [End_Date]
    ,[Date of Record]
    ,[Equipment] AS EQ
    ,[Down Category]
    ,[Failure Mode] AS FM
    ,[Equipment] + ' - ' + [Failure Mode] AS id

    INTO #t2
FROM
(
    SELECT 19.92472222 AS [Duration (hours)], '17-Jul-2016 10:04:31' AS [Event Start],'18-Jul-2016 06:00:00' AS [Event Finsh],'2016-07-17 ' AS [Date of Record],'CART43 ' AS [Equipment],'Breakdown ' AS [Down Category],'NO LABOUR ' AS [Failure Mode]
    UNION ALL SELECT 12, '18-Jul-2016 06:00:00 ','18-Jul-2016 18:00:00 ','2016-07-18 ','CART43 ','Breakdown ','NO LABOUR '
    UNION ALL SELECT 12, '18-Jul-2016 18:00:00 ','19-Jul-2016 06:00:00 ','2016-07-18 ','CART43 ','Breakdown ','NO PARTS AVAILABLE '
    UNION ALL SELECT 12, '19-Jul-2016 06:00:00 ','19-Jul-2016 18:00:00 ','2016-07-19 ','CART43 ','Breakdown ','NO LABOUR '
    UNION ALL SELECT 12, '19-Jul-2016 18:00:00 ','20-Jul-2016 06:00:00 ','2016-07-19 ','CART43 ','Breakdown ','NO PARTS AVAILABLE '
    UNION ALL SELECT 24, '20-Jul-2016 06:00:00 ','21-Jul-2016 06:00:00 ','2016-07-20 ','CART43 ','Breakdown ','NO PARTS AVAILABLE '
    UNION ALL SELECT 0.200277778, '21-Jul-2016 06:00:00 ','21-Jul-2016 06:12:01 ','2016-07-21 ','CART43 ','Breakdown ','NO PARTS AVAILABLE '
    UNION ALL SELECT 18.70138889, '18-Jul-2016 11:17:55 ','19-Jul-2016 06:00:00 ','2016-07-18 ','CART1 ','Planned Down ','SCHEDULED DOWN '
    UNION ALL SELECT 1.305277778, '19-Jul-2016 06:00:00 ','19-Jul-2016 07:18:19 ','2016-07-19 ','CART1 ','Planned Down ','SCHEDULED DOWN '
    UNION ALL SELECT 4.195, '19-Jul-2016 07:18:19 ','19-Jul-2016 11:30:01 ','2016-07-19 ','CART1 ','Breakdown Other ','SCHEDULED DOWN OVERRUN '
    UNION ALL SELECT 0.200555556, '20-Jul-2016 11:53:12 ','20-Jul-2016 12:05:14 ','2016-07-20 ','CART1 ','Breakdown ','WHEEL '
    UNION ALL SELECT 2.542777778, '20-Jul-2016 12:21:15 ','20-Jul-2016 14:53:49 ','2016-07-20 ','CART1 ','Breakdown ','CONTROL '
    UNION ALL SELECT 3.985, '20-Jul-2016 18:43:49 ','20-Jul-2016 22:42:55 ','2016-07-20 ','CART1 ','Breakdown ','HYDRAULICS '
    UNION ALL SELECT 4.694722222, '21-Jul-2016 01:18:19 ','21-Jul-2016 06:00:00 ','2016-07-20 ','CART1 ','Breakdown ','MEASURE '
    UNION ALL SELECT 0.200277778, '21-Jul-2016 06:00:00 ','21-Jul-2016 06:12:01 ','2016-07-21 ','CART1 ','Breakdown ','MEASURE '
) TB


SELECT [Eq], [FM], MIN([Start_Date]) AS [Event Start], MAX(EF2) AS [Event Finish]
FROM
(
    SELECT [T1].[Eq]
    , [T1].[FM]
    , [T1].[Start_Date]
    , [T1].[End_Date] 
    , ISNULL([T2].[End_Date],[T1].[End_Date] ) AS [EF2]
    FROM #t2 [T1]
    LEFT JOIN #t2 [T2] ON 
            [T1].[Eq]=[T2].[Eq]
        AND [T1].[FM] = [T2].[FM] 
        AND [T1].[End_Date]=[T2].[Start_Date]
) AS TB
GROUP BY [Eq], [FM], [EF2]
ORDER BY [Eq], MIN([Start_Date]) 

1 个答案:

答案 0 :(得分:0)

试试这个

DROP Table #t2
SELECT 
    [Duration (hours)]
    ,CAST(LTRIM(RTRIM([Event Start])) AS DATETIME) AS [Start_Date]
    ,CAST(LTRIM(RTRIM([Event Finsh])) AS DATETIME) AS [End_Date]
    ,[Date of Record]
    ,[Equipment] AS EQ
    ,[Down Category]
    ,[Failure Mode] AS FM
    ,[Equipment] + ' - ' + [Failure Mode] AS id

    INTO #t2
FROM
(
    SELECT 19.92472222 AS [Duration (hours)], '17-Jul-2016 10:04:31' AS [Event Start],'18-Jul-2016 06:00:00' AS [Event Finsh],'2016-07-17 ' AS [Date of Record],'CART43 ' AS [Equipment],'Breakdown ' AS [Down Category],'NO LABOUR ' AS [Failure Mode]
    UNION ALL SELECT 12, '18-Jul-2016 06:00:00 ','18-Jul-2016 18:00:00 ','2016-07-18 ','CART43 ','Breakdown ','NO LABOUR '
    UNION ALL SELECT 12, '18-Jul-2016 18:00:00 ','19-Jul-2016 06:00:00 ','2016-07-18 ','CART43 ','Breakdown ','NO PARTS AVAILABLE '
    UNION ALL SELECT 12, '19-Jul-2016 06:00:00 ','19-Jul-2016 18:00:00 ','2016-07-19 ','CART43 ','Breakdown ','NO LABOUR '
    UNION ALL SELECT 12, '19-Jul-2016 18:00:00 ','20-Jul-2016 06:00:00 ','2016-07-19 ','CART43 ','Breakdown ','NO PARTS AVAILABLE '
    UNION ALL SELECT 24, '20-Jul-2016 06:00:00 ','21-Jul-2016 06:00:00 ','2016-07-20 ','CART43 ','Breakdown ','NO PARTS AVAILABLE '
    UNION ALL SELECT 0.200277778, '21-Jul-2016 06:00:00 ','21-Jul-2016 06:12:01 ','2016-07-21 ','CART43 ','Breakdown ','NO PARTS AVAILABLE '
    UNION ALL SELECT 18.70138889, '18-Jul-2016 11:17:55 ','19-Jul-2016 06:00:00 ','2016-07-18 ','CART1 ','Planned Down ','SCHEDULED DOWN '
    UNION ALL SELECT 1.305277778, '19-Jul-2016 06:00:00 ','19-Jul-2016 07:18:19 ','2016-07-19 ','CART1 ','Planned Down ','SCHEDULED DOWN '
    UNION ALL SELECT 4.195, '19-Jul-2016 07:18:19 ','19-Jul-2016 11:30:01 ','2016-07-19 ','CART1 ','Breakdown Other ','SCHEDULED DOWN OVERRUN '
    UNION ALL SELECT 0.200555556, '20-Jul-2016 11:53:12 ','20-Jul-2016 12:05:14 ','2016-07-20 ','CART1 ','Breakdown ','WHEEL '
    UNION ALL SELECT 2.542777778, '20-Jul-2016 12:21:15 ','20-Jul-2016 14:53:49 ','2016-07-20 ','CART1 ','Breakdown ','CONTROL '
    UNION ALL SELECT 3.985, '20-Jul-2016 18:43:49 ','20-Jul-2016 22:42:55 ','2016-07-20 ','CART1 ','Breakdown ','HYDRAULICS '
    UNION ALL SELECT 4.694722222, '21-Jul-2016 01:18:19 ','21-Jul-2016 06:00:00 ','2016-07-20 ','CART1 ','Breakdown ','MEASURE '
    UNION ALL SELECT 0.200277778, '21-Jul-2016 06:00:00 ','21-Jul-2016 06:12:01 ','2016-07-21 ','CART1 ','Breakdown ','MEASURE '        
) TB    

DROP Table #TempTable

SELECT 
    *,  
    ROW_NUMBER() OVER (ORDER BY Start_Date) AS RowId    
INTO #TempTable
FROM 
    #t2


DROP Table #Result
SELECT
    FM, 
    SUM(R.[Duration (hours)]) AS [Duration (hours)],
    MAX(R.End_Date) AS End_Date,
    MIN(R.RowId) AS RowId   
INTO #Result
FROM
(
    SELECT
        A.[Duration (hours)] ,
        A.Start_Date ,
        A.End_Date ,
        A.[Date of Record] ,
        A.EQ ,
        A.[Down Category] ,
        A.FM ,
        A.id ,
        A.RowId,
        CASE WHEN A.FM = B.FM OR A.FM = C.FM THEN -1 ELSE A.RowId END ISContinue        
    FROM
        #TempTable A LEFT JOIN 
        (SELECT (RowId + 1) AS RowId, FM FROM #TempTable) B ON A.RowId = B.RowId LEFT JOIN 
        (SELECT (RowId -1) AS RowId, FM FROM #TempTable) C ON A.RowId = C.RowId
  ) R
GROUP BY 
    R.FM,
    R.ISContinue    


SELECT
    R.[Duration (hours)],
    T.Start_Date ,
    R.End_Date ,
    T.[Date of Record] ,
    T.EQ ,
    T.[Down Category] ,
    T.FM ,
    T.id 
FROM
    #Result R INNER JOIN        
    #TempTable T ON R.RowId = T.RowId
ORDER BY 
    T.Start_Date

输出

enter image description here