2015-11-09 12 views
0

Разделение часов между несколькими днямиРазделительные часы между датами в зависимости от диапазона дат

У меня есть данные как это.

StartDate  EndDate 
2015-10-05 20:00:00.000 2015-10-06 12:00:00.000 

Мне нужно эти данные должны быть разделены по дате, как

2015-10-05 240 (4 hours) 
2015-10-06 720 (12 hours) 

я могу получить первый раскол даты начала, как этот

 select (StartDate as date) as StartDate, 
      DATEDIFF(minute, StartDate, dateadd(day, 1, Cast(StartDate as date))) as diff   
     from t 

, который дает мне

2015-10-05 240 

И получить данные даты окончания, например

 select 
      Cast(EndDate as date) as StartDate, 
      DATEDIFF(minute, Cast(EndDate as date), EndDate) as diff     
     from t 


2015-10-06 720 

Но я не уверен, как это сделать в одном запросе. Кроме того, время дифференциалов Betweens начало и конец может быть больше, чем один день разница как этот

StartDate  EndDate 
2015-10-05 20:00:00.000 2015-10-08 12:00:00.000 

, для которого мне нужно

2015-10-05 240 
2015-10-06 1440 
2015-10-07 1440 
2015-10-06 720 

Спасибо за глядя

+0

Это, кажется, SQL Server, но какая версия? – Shnugo

+0

Свой 2012. Обновленный тег. Благодарю. – user3606175

ответ

1

Попробуйте так:

Примечание. Если полный интервал может быть более 10 дней, просто добавьте еще несколько значений в таблицу подсчета. Внимание: Это решение пока не охватывает ситуацию, когда начало и конец в тот же день ...

DECLARE @d1 DATETIME={ts'2015-10-05 08:00:00'}; 
DECLARE @d2 DATETIME={ts'2015-10-07 12:00:00'}; 

WITH SomePreCalculations AS 
(
    SELECT @d1 AS D1 
      ,@d2 AS D2 
      ,CAST(@d1 AS DATE) AS StartDate 
      ,DATEADD(DAY,1,CAST(@d1 AS DATE)) AS FirstMidnight 
      ,CAST(@d2 AS DATE) AS LastMidnight 
) 
,Differences AS 
(
    SELECT * 
      ,DATEDIFF(MINUTE,D1,FirstMidnight) AS TilMidnight 
      ,DATEDIFF(MINUTE,LastMidnight,D2) AS FromMidnight 
    FROM SomePreCalculations 
) 
,TallyTable AS 
(
    SELECT RowInx FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS x(RowInx) 
) 
SELECT CAST(Date AS DATE),Minutes FROM 
(
     SELECT 0 AS Inx, D1 AS Date, TilMidnight AS Minutes 
     FROM Differences 
UNION SELECT RowInx,(SELECT DATEADD(DAY,RowInx,(SELECT StartDate FROM SomePreCalculations))),1440 
     FROM TallyTable 
     WHERE DATEADD(DAY,RowInx,(SELECT StartDate FROM SomePreCalculations))<(SELECT LastMidnight FROM SomePreCalculations) 
UNION SELECT 99 AS Inx, D2, FromMidnight 
     FROM Differences 
) AS tbl 
ORDER BY tbl.Inx 
+0

Спасибо Шнуго. Я изучаю это. – user3606175

+0

Спасибо. Это потрясающе. – user3606175

+0

@ user3606175, рад помочь вам! – Shnugo

2

Это должно охватывать, когда начало и конец в тот же день и без ограничений по дням

EDIT: исправлена ​​ошибка с неправильным вычислением на дату окончания

declare @StartDate datetime, @EndDate datetime 
set @StartDate = '2015-10-05 20:00' 
set @EndDate = '2015-10-05 21:00' 

;WITH cte AS 
(
    SELECT cast(@StartDAte as date) StartDate, 
      cast(dateadd(day, 1, @StartDAte) as date) EndDate 
    UNION ALL 
    SELECT DATEADD(day, 1, StartDate) StartDate, 
      DATEADD(day, 2, StartDate) EndOfDate 
    FROM cte 
    WHERE DATEADD(day, 1, StartDate) <= @EndDate 
) 
select StartDate, 
    case 
     when cast(@StartDate as date) = cast(@EndDate as date) then datediff(minute, @StartDate, @EndDate) 
     when StartDate = cast(@StartDate as date) then datediff(minute, @StartDate, cast(EndDate as datetime)) 
     when StartDate = cast(@EndDate as date) then datediff(minute, cast(StartDate as datetime), @EndDate) 
     else 1440 end 
from cte 
+0

Мне нравится ваш рекурсивный подход, но есть один недостаток. Кажется, он просчитал последний день (разница до следующей полуночи, а не прошлых минут дня). – Shnugo

+0

Пожалуйста, попробуйте сейчас. Я использовал дату окончания 12:00 и не заметил вопроса, потому что это было 720 независимо от того, с какой стороны вы смотрите :) – shurik

+0

Смешные, +1 с моей стороны – Shnugo

Смежные вопросы