find start and stop date for contiguous dates in multiple rows

后端 未结 1 732
生来不讨喜
生来不讨喜 2021-01-03 17:23

I\'m having a bit of trouble displaying correct data from my table. Im not really sure what to search for either. Im not sure min(column) or max(column) will help me here.

相关标签:
1条回答
  • 2021-01-03 18:27

    The old answer had a weakness: every row is checked only with the previous to verify if the period are overlapping, if an earlier row have a period that last more the logic will not consider it. For example:

    Code | DateStart           | DateFrom            | Overlap
    -----+---------------------+---------------------+---------
    1006 | 2014-06-18 07:00:00 | 2014-06-18 19:00:00 | 0 
    1006 | 2014-06-18 08:10:00 | 2014-06-18 10:00:00 | 1 
    1006 | 2014-06-18 16:00:00 | 2014-06-18 20:30:00 | 0 <- don't overlap with 
                                                            previous but overlap
                                                            with the first
    

    To improve that PrevStop need to become LastStop and have the value of the max of the previous DateFrom for the Code

    With N AS (
      SELECT Code, DateFrom, DateTo
           , LastStop = MAX(DateTo) 
                        OVER (PARTITION BY Code ORDER BY DateFrom, DateTo 
                              ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
      FROM   Table1
    ), B AS (
      SELECT Code, DateFrom, DateTo
           , Block = SUM(CASE WHEN LastStop Is Null Then 1
                              WHEN LastStop < DateFrom Then 1
                              ELSE 0
                        END)
                     OVER (PARTITION BY Code ORDER BY DateFrom, LastStop)
      FROM   N
    )
    SELECT Code
         , MIN(DateFrom) DateFrom
         , MAX(DateTo) DateTo
    FROM   B
    GROUP BY Code, Block
    ORDER BY Code, Block
    

    SQLFiddle Demo

    ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING is needed to remove the current row from theMAX.


    Old Answer

    This query works only every the period is not completely inside the precedent.

    The idea is to check for every row if it is linked with the next/previous one.
    If rows are linked they form a block and they will be grouped together to get the first DateFrom and the last DateTo

    With N AS (
      SELECT Code, DateFrom, DateTo
           , PrevStop = LAG(DateTo, 1, NULL) 
                        OVER (PARTITION BY Code ORDER BY DateFrom)
      FROM   Table1
    ), B AS (
      SELECT Code, DateFrom, DateTo
           , Block = SUM(CASE WHEN PrevStop Is Null Then 1
                              WHEN PrevStop < DateFrom Then 1
                              ELSE 0
                         END)
                     OVER (PARTITION BY Code ORDER BY PrevStop)
      FROM   N
    )
    SELECT Code
         , MIN(DateFrom) DateFrom
         , MAX(DateTo) DateTo
    FROM   B
    GROUP BY Code, Block
    ORDER BY Code, Block
    

    SQLFiddle demo with some data added to check with more block on the same code/day

    The query search for the block starter checking every row if they are the first for the code (PrevStop IS NULL) or if they are outside the previous one (PrevStop < DateFrom).

    The windowed SUM retrieve only the previous row by the ORDER to create costant value for block of linked data, for example with the test data we will get

    Code | DateStart           | DateFrom            | Starter | Block
    -----+---------------------+---------------------+---------+------
    1006 | 2014-06-18 07:00:00 | 2014-06-18 09:00:00 |       1 |     1
    1006 | 2014-06-18 08:10:00 | 2014-06-18 06:00:00 |       0 |     1
    1006 | 2014-06-18 08:00:00 | 2014-06-18 08:30:00 |       0 |     1
    1006 | 2014-06-18 07:00:00 | 2014-06-18 07:30:00 |       1 |     2
    1006 | 2014-06-18 08:00:00 | 2014-06-18 08:30:00 |       1 |     3
    1006 | 2014-06-18 08:10:00 | 2014-06-18 09:00:00 |       0 |     3
    3006 | 2014-06-18 07:00:00 | 2014-06-18 08:00:00 |       1 |     1
    3006 | 2014-06-18 09:00:00 | 2014-06-18 10:00:00 |       1 |     2
    

    grouping by Code and Block get the result

    0 讨论(0)
提交回复
热议问题