![](/img/trans.png)
[英]How to split a date range in a row into time spent in each hour in a day in SQL
[英]SQL Server How to break apart each hour from a time range
我正在尝试计算日期范围内每小时的分钟数。
我希望它返回每个小时的分钟数。 如果开始时间是12:38PM
,结束时间是1:18PM
,它将在12PM
列中输入22
,在1PM
列中输入18
。 我希望找到一种方法来创建所需的24 hour
专栏。
然后再创建24列,并采用Units_Sold/Minutes
然后将它们乘以每小时的minutes
,以得出每小时出售的平均总单位数。
这就是我在Excel中使其看起来像线
SELECT account_number,
asset_number,
units_sold,
minutes,
open_date,
start_time,
end_time
FROM sales
这样做感觉很奇怪,但是肯定有可能。 我将为您提供TSQL的起点,但是应该翻译一下。 这几乎是蛮力的,因此,如果要大规模执行此操作,我会寻找一种聪明/高效的替代方法。
另外,我假设我们没有度过日子,但这可以很轻松地处理,可能使用“朱利安小时”之类的东西,我认为这不是真实的,但会像朱利安日那样 。
--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
使用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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.