2014-11-20 3 views
0

Я пытаюсь вычислить количество минут в час в диапазоне дат.SQL Server Как разбить каждый час из диапазона времени

Я бы хотел, чтобы он возвращал количество минусов, которые находятся в каждом часе. Если время начала: 12:38PM, а время окончания - 1:18PM, оно должно было бы ввести 22 в колонке 12PM и 18 в столбце 1PM. Я надеюсь найти способ создать необходимые столбцы 24 hour.

А затем создайте еще 24 столбца и возьмите Units_Sold/Minutes и умножьте их на minutes в каждый час, чтобы получить среднее количество единиц, проданных за час.

Это то, что я сделал это смотреть строку в Excel

screenshot

SELECT account_number, 
     asset_number, 
     units_sold, 
     minutes, 
     open_date, 
     start_time, 
     end_time 
FROM sales 
+0

Могут ли раз пересечь полночь? Покрывать целые дни? Любой особый вкус SQL? –

+0

И добро пожаловать в SO, кстати. Традиционно целесообразно t показать некоторую попытку, которую вы сделали в качестве отправной точки. –

ответ

0

Это чувствовать себя странным, что нужно сделать, но это, конечно, возможно. Я дам вам отправную точку в TSQL, но он должен перевести. Это довольно грубая сила, поэтому я бы поискал умную/эффективную альтернативу, если бы делал это в значительных масштабах.

Кроме того, я предположил, что мы не пересекаем дни, но это может быть довольно легко обрабатывать, возможно, используя что-то вроде «Юлийских часов», которое я не считаю реальным, но будет действовать как Julian day.

--set up a test table a couple test cases 
DECLARE @tbl TABLE(start_time DATETIME2,end_time DATETIME2) 
INSERT INTO @tbl VALUES ('2014-11-19 21:08:00.190', '2014-11-19 22:08:00.190') 
INSERT INTO @tbl VALUES ('2014-11-19 20:08:00.190', '2014-11-19 22:08:00.190') 

--use a common table expression to get the time parts (could be just a subquery) 
;WITH cte AS (
SELECT * 
     ,DATEPART(HH,start_time) start_hour 
     ,DATEPART(MINUTE,start_time) start_min 
     ,DATEPART(HH,end_time) end_hour 
     ,DATEPART(MINUTE,end_time) end_min 
    FROM @tbl 
) 
SELECT * 
     ,CASE 
     WHEN end_hour < 0 THEN 0 --not real case for hour 0 
     WHEN start_hour > 0 THEN 0 
     WHEN end_hour = 0 AND start_hour = 0 THEN end_min - start_min 
     WHEN start_hour = 0 AND end_hour > 0 THEN 60 - start_min 
     WHEN start_hour < 0 AND end_hour = 0 THEN end_min --not real case for hour 0 
     ELSE 60 
     END [00] 
     --... 
     ,CASE 
     WHEN end_hour < 21 THEN 0 --not real case for hour 0 
     WHEN start_hour > 21 THEN 0 
     WHEN end_hour = 21 AND start_hour = 21 THEN end_min - start_min 
     WHEN start_hour = 21 AND end_hour > 21 THEN 60 - start_min 
     WHEN start_hour < 21 AND end_hour = 21 THEN end_min --not real case for hour 0 
     ELSE 60 
     END [21] 
     ,CASE 
     WHEN end_hour < 22 THEN 0 
     WHEN start_hour > 22 THEN 0 
     WHEN end_hour = 22 AND start_hour = 22 THEN end_min - start_min 
     WHEN start_hour = 22 AND end_hour > 22 THEN 60 - start_min 
     WHEN start_hour < 22 AND end_hour = 22 THEN end_min 
     ELSE 60 
     END [22] 
     --etc. 
    FROM cte 
0

Использование spt_values получить 24 часов, а затем присоединиться к таблице, чтобы получить каждые часы минуты, наконец шарниром 24 колонн.

with hours as 
(
select number as hour 
    from master..spt_values 
    where number between 0 and 23 AND TYPE='P' 
), 
your_table as 
(
select convert(datetime , '2014-11-19 00:00:00.000') as start_dt 
     ,convert(datetime , '2014-11-19 23:59:00.000') as end_dt 
union 
select convert(datetime , '2014-11-19 20:00:00.000') as start_dt 
     ,convert(datetime , '2014-11-20 19:59:00.000') as end_dt 
), 
minutes as 
(
select 
    t.start_dt,t.end_dt,h.hour, 
    case 
     when datepart(hour,t.start_dt)=datepart(hour,t.end_dt) 
     then datepart(MINUTE,t.end_dt)-datepart(MINUTE,t.end_dt) 
     when datepart(hour,t.start_dt) = h.hour 
     then 60 - datepart(MINUTE,t.start_dt) 
     when datepart(hour,t.end_dt) = h.hour 
     then datepart(MINUTE,t.end_dt) 
     else 60 end as minutes 
from your_table t 
join hours h 
    on (datediff(day,t.start_dt,t.end_dt)=0 and h.hour between datepart(hour,t.start_dt) and datepart(hour,t.end_dt)) 
    or (datediff(day,t.start_dt,t.end_dt)=1 and (h.hour <= datepart(hour,t.start_dt) or h.hour >= datepart(hour,t.end_dt))) 
) 
select 
    start_dt, 
    end_dt, 
    [0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11], 
    [12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23] 
from minutes 
pivot (max(minutes) for hour 
     in ([0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11], 
      [12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23] 
     )) as p 

Результат:

START_DT   END_DT    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 
19 Nov 2014 00:00 19 Nov 2014 23:59 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 59 
19 Nov 2014 20:00 20 Nov 2014 19:59 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 59 60 60 60 60 

SQL Fiddle Demo

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