SQL Server如何从时间范围中分解每小时

时间:2014-11-20 01:36:10

标签: sql sql-server time

我正在尝试计算日期范围内每小时的分钟数。

我希望它能够返回每小时的小步数。如果开始时间为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

2 个答案:

答案 0 :(得分:0)

这感觉有点奇怪,但肯定有可能。我会给你一个TSQL的起点,但它应该翻译。这是非常蛮力的,所以如果大规模地这样做,我会寻找一个聪明/有效的替代方案。

另外,我认为我们不会过几天,但这可能很容易处理,可能使用像" Julian hours"我不认为是真实的,但会像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

答案 1 :(得分: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