Вопрос

Similar Question: Crosstabbing rows based on sequence islands in a list of times

Take the following example data:

Employ     Date          Duration
0000001    2012-11-12    9.00
0000001    2012-11-13    9.00
0000001    2012-11-14    9.00
0000001    2012-11-16    9.00
0000001    2012-11-17    9.00
0000002    2012-11-04    9.00
0000002    2012-11-05    9.00
0000002    2012-11-06    9.00
0000003    2012-11-01    9.00
0000004    2012-11-02    6.50

I'm trying to transform this as follows:

Employ     Start Date    End Date      Days    TotalDuration
0000001    2012-11-12    2012-11-14    3       27
0000001    2012-11-16    2012-11-17    2       18
0000002    2012-11-04    2012-11-06    3       27
0000003    2012-11-01    2012-11-01    1       9.00
0000004    2012-11-02    2012-11-02    1       6.50

Using the linked question above i've tried doing this as follows:

WITH    ExampleData ( [DET_NUMBERA], [Date], [Duration] )
          AS ( 
                SELECT '0000001' AS [DET_NUMBERA], CONVERT(DATE, '12/11/2012', 103) AS [Date], 9.00 AS [Duration]
                UNION ALL
                SELECT '0000001', CONVERT(DATE, '13/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000001', CONVERT(DATE, '14/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000001', CONVERT(DATE, '16/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000001', CONVERT(DATE, '17/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000002', CONVERT(DATE, '04/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000002', CONVERT(DATE, '05/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000002', CONVERT(DATE, '06/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000003', CONVERT(DATE, '01/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000004', CONVERT(DATE, '02/11/2012', 103), 6.5
             ),
        CrossTabPrep
          AS ( SELECT   [DET_NUMBERA] ,
                        [Date] ,
                        [Duration] ,
                        CONVERT(INT, CONVERT(VARCHAR(10), GETDATE(), 112)) - ROW_NUMBER() OVER ( PARTITION BY [DET_NUMBERA] ORDER BY [Date] ) AS [Grp]
               FROM     ExampleData
             ),
        FinalRender ( [DET_NUMBERA], [Start Date], [End Date], [Days], [Duration] )
          AS ( SELECT   [DET_NUMBERA] ,
                        MIN([Date]) AS [Start Date] ,
                        MAX([Date]) AS [End Date] ,
                        ISNULL(DATEDIFF(DAY, MIN([Date]), MAX([Date])), 0) AS [Days] ,
                        SUM([Duration]) AS [Duration]
               FROM     CrossTabPrep
               GROUP BY [DET_NUMBERA] ,
                        [Grp]
             )
    SELECT  *
    FROM    FinalRender
    ORDER BY [DET_NUMBERA]

But its not quite working - ive gone wrong somewhere - how do i tweak this SQL to transform as described above.

Это было полезно?

Решение 2

Doh! i was using getDate() in my Grp Identifier instead of the [Date] column!

Revised as follows - works fine & handles breaks:

WITH    ExampleData ( [DET_NUMBERA], [Date], [Duration] )
          AS ( 
                SELECT '0000001' AS [DET_NUMBERA], CONVERT(DATE, '12/11/2012', 103) AS [Date], 9.00 AS [Duration]
                UNION ALL
                SELECT '0000001', CONVERT(DATE, '13/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000001', CONVERT(DATE, '14/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000001', CONVERT(DATE, '16/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000001', CONVERT(DATE, '17/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000002', CONVERT(DATE, '04/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000002', CONVERT(DATE, '05/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000002', CONVERT(DATE, '06/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000003', CONVERT(DATE, '01/11/2012', 103), 9.00
                UNION ALL
                SELECT '0000004', CONVERT(DATE, '02/11/2012', 103), 6.5
             ),
        CrossTabPrep
          AS ( SELECT   [DET_NUMBERA] ,
                        [Date] ,
                        [Duration] ,
                        CONVERT(INT, CONVERT(VARCHAR(10), [Date], 112)) - ROW_NUMBER() OVER ( PARTITION BY [DET_NUMBERA] ORDER BY [Date] ) AS [Grp]
               FROM     ExampleData
             ),
        FinalRender ( [DET_NUMBERA], [Start Date], [End Date], [Days], [Duration] )
          AS ( SELECT   [DET_NUMBERA] ,
                        MIN([Date]) AS [Start Date] ,
                        MAX([Date]) AS [End Date] ,
                        ISNULL(DATEDIFF(DAY, MIN([Date]), MAX([Date])), 0) + 1 AS [Days] ,
                        SUM([Duration]) AS [Duration]
               FROM     CrossTabPrep
               GROUP BY [DET_NUMBERA] ,
                        [Grp]
             )
    SELECT  *
    FROM    FinalRender
    ORDER BY [DET_NUMBERA]

Другие советы

Part of the problem is in the FinalRender you have a GROUP BY on the [Grp] field. This is making the values DISTINCT which is throwing off your totals:

WITH    ExampleData ( [DET_NUMBERA], [Date], [Duration] )
  AS ( 
        SELECT '0000001' AS [DET_NUMBERA], CONVERT(DATE, '12/11/2012', 103) AS [Date], 9.00 AS [Duration]
        UNION ALL
        SELECT '0000001', CONVERT(DATE, '13/11/2012', 103), 9.00
        UNION ALL
        SELECT '0000001', CONVERT(DATE, '14/11/2012', 103), 9.00
        UNION ALL
        SELECT '0000001', CONVERT(DATE, '15/11/2012', 103), 9.00
        UNION ALL
        SELECT '0000001', CONVERT(DATE, '16/11/2012', 103), 9.00
        UNION ALL
        SELECT '0000002', CONVERT(DATE, '04/11/2012', 103), 9.00
        UNION ALL
        SELECT '0000002', CONVERT(DATE, '05/11/2012', 103), 9.00
        UNION ALL
        SELECT '0000002', CONVERT(DATE, '06/11/2012', 103), 9.00
        UNION ALL
        SELECT '0000003', CONVERT(DATE, '01/11/2012', 103), 9.00
        UNION ALL
        SELECT '0000004', CONVERT(DATE, '02/11/2012', 103), 6.5
     ),
CrossTabPrep
  AS ( SELECT   [DET_NUMBERA] ,
                [Date] ,
                [Duration] ,
                CONVERT(INT, CONVERT(VARCHAR(10), GETDATE(), 112)) - ROW_NUMBER() OVER ( PARTITION BY [DET_NUMBERA] ORDER BY [Date] ) AS [Grp]
       FROM     ExampleData
     ),
FinalRender ( [DET_NUMBERA], [Start Date], [End Date], [Days], [Duration] )
  AS ( SELECT   [DET_NUMBERA] ,
                MIN([Date]) AS [Start Date] ,
                MAX([Date]) AS [End Date] ,
                ISNULL(DATEDIFF(DAY, MIN([Date]), MAX([Date])), 0) AS [Days] ,
                SUM([Duration]) AS [Duration]
       FROM     CrossTabPrep
       GROUP BY [DET_NUMBERA] 
     )
SELECT  *
FROM    FinalRender
ORDER BY [DET_NUMBERA]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top