将单个事务拆分为n行,每天一行

时间:2016-06-15 00:14:52

标签: sql sql-server

我想将跨越多天的单个事务(如START_DATE_TIME和END_DATE_TIME所示)拆分为 n 行,每天一行。例如:

nil

应该成为:

START_DATE_TIME       END_DATE_TIME          PRICE
20160101 20:00:00     20160104 04:00:00      1.999

任何想法如何做到这一点?

我已经知道 n < = 2了,但除此之外,我的方法变得非常复杂。我正在使用SSMS 2012。

提前致谢!

(请忽略上面的错误格式 - 我在这里的第一篇文章,仍在学习绳索!)

2 个答案:

答案 0 :(得分:1)

好吧,如果你有numbers表,你可以很容易地做到这一点。您可以构建一个足以满足master.spt_values的大多数目的的

with n as (
      select row_number() over (order by (select null)) - 1 as n
      from master.spt_values
     )
select (case when n.n = 0 then t.start_date_time
             else dateadd(day, n.n, cast(t.start_date_time) as date))
        end) as start_date_time,
       (case when dateadd(day, n.n, cast(t.start_date_time as date)) > t.end_date_time
             then end_date_time
             else dateadd(day, n.n, cast(t.start_date_time as date))
        end) as end_date_time,
       price
from t join
     n
     on date_add(day, n, cast(t.start_date_time as date)) <= t.end_date_time;

答案 1 :(得分:0)

考虑使用具有交叉连接的递归CTE。 Case语句用于捕获开始时间戳和结束时间戳:

DROP TABLE #tempData;
CREATE TABLE #tempData (START_DATE_TIME DateTime, 
                        END_DATE_TIME DateTime, Price Decimal(5,2));
INSERT #tempData(START_DATE_TIME, END_DATE_TIME, Price)
VALUES ('2016-01-01 20:00:00', '20160104 04:00:00', 1.99);

DECLARE @start DateTime;
DECLARE @end DateTime;

SELECT @start = #tempData.START_DATE_TIME, @end = #tempData.END_DATE_TIME
FROM #tempData;

WITH dates AS (
    SELECT @start AS START_DATE_TIME
    UNION ALL
    SELECT CAST(CAST(DateAdd(Day, 1, START_DATE_TIME) As Date) As DateTime)
    FROM  dates
    WHERE START_DATE_TIME < @end - 1
)

SELECT dates.START_DATE_TIME,    
   CASE WHEN CAST(dates.START_DATE_TIME AS Date) = CAST(#tempData.END_DATE_TIME As Date)
        THEN #tempData.END_DATE_TIME
        WHEN CAST(dates.START_DATE_TIME AS Date) = CAST(#tempData.START_DATE_TIME As Date)
        THEN CAST(CAST(DateAdd(Day, 1, dates.START_DATE_TIME) As Date) As DateTime)
        ELSE DateAdd(Day, 1, dates.START_DATE_TIME)
   END AS END_DATE_TIME,    
   #tempData.Price

 FROM dates
 CROSS JOIN #tempData
;