按小时获取日期范围内的分钟

时间:2018-11-01 20:17:45

标签: sql sql-server

我正在尝试编写一个SQL查询(SQL Server),其中一部分是确定两个日期时间之间每小时的分钟数。

例如:11/1/2018 09:05-11/1/2018 13:15

小时09:55分钟
10小时:60分钟
11小时:60分钟
12小时:60分钟
13小时:15分钟

然后将它们放入临时表中,并与其他一些数据分组,然后将这些数据用于根据这些分钟来计算美元金额。

是否有一种方法可以通过SQL完成不太慢或很费力的事情?

谢谢!

3 个答案:

答案 0 :(得分:1)

我认为递归CTE可能是最好的方法:

with cte as (
      select startTime, endTime,
             startTime_hour as hourStart,
             (case when endTime < dateadd(hour, 1, startTime_hour) then endTime
                   else dateadd(hour, 1, startTime_hour)
              end) as hourEnd
      from (select t.*,
                   dateadd(hour, datediff(hour, 0, startTime), 0) as startTime_hour
            from t
           ) t
      union all
      select startTime, endTime,
             dateadd(hour, 1, hourStart) as hourStart,
             (case when endTime < dateadd(hour, 2, hourStart) then endTime
                   else dateadd(hour, 2, hourStart)
              end) as endHour
      from cte
      where hourEnd < endTime
     )
select cte.hourStart,
       (case when hourStart > startTime then datediff(minute, hourStart, hourEnd) else datediff(minute, startTime, hourEnd) end) as minutes
from cte
order by hourStart;

Here是db <>小提琴。

答案 1 :(得分:0)

样本数据

下面,我们将四个时间范围以及相关的值抽到表中。所有时间范围都不同,但前两个时间间隔为10h 30m。后两个相距9h 45m。

declare @times table (
    startTime time,
    endTime time,
    val float
);

insert @times values 
    ('2018-10-01 01:00:00', '2018-10-01 10:45:00', 7),
    ('2018-10-02 01:00:00', '2018-10-02 10:45:00', 8),
    ('2018-10-01 01:00:00', '2018-10-01 11:30:00', 1),
    ('2018-10-02 01:00:00', '2018-10-02 11:30:00', 3);

解决方案

您可以根据需要使用“ datediff”功能进行汇总。使用取模运算符可以将您的分钟数转换为仅折扣整个小时数后剩余的分钟数。

select      ap.h,
            ap.m,
            sumVal = sum(val)
from        @times
cross apply (select 
                h = datediff(hour, startTime, endTime),
                m = datediff(minute, startTime, endTime) % 60
            ) ap
group by    ap.h,
            ap.m

答案 2 :(得分:0)

这是替代的动态解决方案,您只能使用两个参数(开始/结束日期):

create table #temp
([hour] int, [minutes] int)

declare @startTime datetime='11/1/2018 09:05'
declare @EndTime datetime='11/1/2018 13:15'

declare @tempStartTime datetime = @startTime
declare @nextTimeRounded datetime

declare @hourdiff int = DATEDIFF(HOUR,@startTime,@EndTime)
declare @counter int = DATEPART(HH,@startTime)
declare @limit int = @counter + @hourdiff + 1 

while @counter < @limit
begin
   insert into #temp ([hour]) values (@counter)

   set @nextTimeRounded= (dateadd(hour, 
                          1 + datepart(hour, @tempStartTime),
                          cast(convert(varchar(10),@tempStartTime, 112) as datetime))
                         )

   if @nextTimeRounded > @EndTime
   begin
      set @nextTimeRounded = @EndTime
   end

   update #temp 
   set [minutes] = (case when DATEDIFF(MINUTE,@tempStartTime,@nextTimeRounded)=0 then 60 else DATEDIFF(MINUTE,@tempStartTime,@nextTimeRounded) end)
   where [hour] = @counter

   set @counter = @counter + 1
   set @tempStartTime = DATEADD(MINUTE,DATEDIFF(MINUTE,@tempStartTime,@nextTimeRounded),@tempStartTime);
end

select * from #temp