按日期和按组SQL划分行

时间:2017-06-07 08:34:25

标签: sql sql-server

我遇到了SQL问题。我找到了类似的TOPIC,但不完全一样。我想分开重叠的日期。例如,我在第一行START_DATE 2014-08-06和2014-12-06 END_DATE。我们可以看到第二行和第三行的日期在第一行的这段时间内,但我必须在STORE_IDINDEX_ID上单独进行。价格应从内部时期开始。我无法修改此代码。你能帮助我吗?

我的表格如下:

declare @t table  (STORE_ID INT, 
                  INDEX_ID INT,
                  START_DATE datetime,
                  END_DATE datetime, 
                  GROSS_SALES_PRICE decimal(10,2)
             );

 insert into @t 
 values (1,20,'2014-08-06 00:00:00.000', '2014-10-06 23:59:59.000', 29.99),
 (1,20,'2014-09-06 00:00:00.000', '2014-09-09 23:59:59.000', 32.99),
 (1,20,'2014-09-10 00:00:00.000', '2014-09-30 23:59:59.000', 32.99),
 (1,20,'2014-10-07 00:00:00.000', '2049-12-31 23:59:59.000', 34.99),
 (1,22,'2014-08-06 00:00:00.000', '2014-10-06 23:59:59.000', 29.99),
 (1,22,'2014-09-06 00:00:00.000', '2014-09-09 23:59:59.000', 32.99),
 (1,22,'2014-09-10 00:00:00.000', '2014-09-30 23:59:59.000', 32.99),
 (1,22,'2014-10-07 00:00:00.000', '2049-12-31 23:59:59.000', 34.99),
 (2,20,'2014-08-06 00:00:00.000', '2014-10-06 23:59:59.000', 29.99),
 (2,20,'2014-09-06 00:00:00.000', '2014-09-09 23:59:59.000', 32.99),
 (2,20,'2014-09-10 00:00:00.000', '2014-09-30 23:59:59.000', 32.99),
 (2,20,'2014-10-07 00:00:00.000', '2049-12-31 23:59:59.000', 34.99) 

所需的输出:

  declare @t2 table (STORE_ID INT, 
                    INDEX_ID INT, 
                    START_DATE datetime,
                    END_DATE datetime, 
                    GROSS_SALES_PRICE decimal(10,2)
                   );

 insert into @t2 
 values (1,20,'2014-08-06 00:00:00.000', '2014-09-05 23:59:59.000', 29.99),
   (1,20,'2014-09-06 00:00:00.000', '2014-09-09 23:59:59.000', 32.99),
   (1,20,'2014-09-10 00:00:00.000', '2014-09-30 23:59:59.000', 32.99),
   (1,20,'2014-10-01 00:00:00.000', '2014-10-06 23:59:59.000', 29.99),
   (1,20,'2014-10-07 00:00:00.000', '2049-12-31 23:59:59.000', 34.99),
   (1,22,'2014-08-06 00:00:00.000', '2014-09-05 23:59:59.000', 29.99),
   (1,22,'2014-09-06 00:00:00.000', '2014-09-09 23:59:59.000', 32.99),
   (1,22,'2014-09-10 00:00:00.000', '2014-09-30 23:59:59.000', 32.99),
   (1,22,'2014-10-01 00:00:00.000', '2014-10-06 23:59:59.000', 29.99),
   (1,22,'2014-10-07 00:00:00.000', '2049-12-31 23:59:59.000', 34.99),
   (2,20,'2014-08-06 00:00:00.000', '2014-09-05 23:59:59.000', 29.99),
   (2,20,'2014-09-06 00:00:00.000', '2014-09-09 23:59:59.000', 32.99),
   (2,20,'2014-09-10 00:00:00.000', '2014-09-30 23:59:59.000', 32.99),
   (2,20,'2014-10-01 00:00:00.000', '2014-10-06 23:59:59.000', 29.99),
   (2,20,'2014-10-07 00:00:00.000', '2049-12-31 23:59:59.000', 34.99)

因此代码应该像我附加的主题一样工作,但它应该在每个STORE_IDINDEX_ID上单独执行。

1 个答案:

答案 0 :(得分:1)

;WITH Preprocessed AS (
    SELECT STORE_ID, INDEX_ID, START_DATE, END_DATE,
        NEXT_START_DATE = FIRST_VALUE(START_DATE) OVER (PARTITION BY STORE_ID, INDEX_ID ORDER BY START_DATE ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING),
        MAX_END_DATE    = MAX(END_DATE) OVER(PARTITION BY STORE_ID, INDEX_ID ORDER BY START_DATE ROWS UNBOUNDED PRECEDING) 
    FROM @t
)
SELECT 
    STORE_ID, INDEX_ID, START_DATE,
    END_DATE_NEW = IIF(NEXT_START_DATE IS NOT NULL AND NEXT_START_DATE < END_DATE, DATEADD(SECOND, -1, NEXT_START_DATE), END_DATE)
FROM Preprocessed

UNION ALL

SELECT STORE_ID, INDEX_ID, 
    START_DATE  = DATEADD(SECOND, 1, END_DATE),
    END_DATE    = IIF(NEXT_START_DATE < MAX_END_DATE, DATEADD(SECOND, -1, NEXT_START_DATE), MAX_END_DATE)
FROM Preprocessed
WHERE (NEXT_START_DATE IS NULL OR NEXT_START_DATE > DATEADD(SECOND, 1, END_DATE))   -- End of the range
    AND (END_DATE < MAX_END_DATE)                                                   -- Check if need to add new record after range
ORDER BY 1, 2, 3