SQL to Split data across hours

Sometimes data spans hours. This code takes something that begins in hour 1 and may not end till hour 2 or 3. It splits it into it's hourly components.

  • HN is hour number

create function [dbo].[ufn_splithours]( @start datetime, @duration int ) returns @res table (
 hn int, starttime datetime, endtime datetime 
)

as
begin
declare @actualend datetime
set @actualend=dateadd(second,@duration, @start)
declare @sdx datetime
set @sdx=dbo.DateOnly(@start)


declare @hnx int
declare @tx table (hn int, starttime datetime, endtime datetime)
SET @HNx=0
WHILE @HNx < 24
BEGIN
  INSERT INTO @Tx SELECT @HNx, @SDx, Dateadd(hh,1,@sdx)
  SET @SDx=DATEADD(HH,1,@SDx)
  SET @HNx=@HNx+1
END



declare @endtime datetime
declare @hourend datetime
declare @hourstart datetime

declare @dtx datetime
set @dtx =@start
declare @rowsx int
set @rowsx=0
while @dtx < @actualend
begin

  	 
   if @rowsx =0
   begin
     -- first entry

	 set @hnx=datepart(hour,@dtx)
	 select @hourstart=starttime, @hourend=endtime from @tx where hn=@hnx
   
     insert into @res select @hnx, @start, @hourend
   
	 set @rowsx=@rowsx+1
   end
   set @dtx=dateadd(second,1,@dtx)
   if datepart(hh, @dtx ) > @hnx
   begin
	 set @hnx=datepart(hour,@dtx)
	 select @hourstart=starttime, @hourend=endtime from @tx where hn=@hnx
   
     if @actualend < @hourend
	   set @hourend=@actualend

   
	 insert into @res select @hnx, @hourstart, @hourend
	 set @rowsx=@rowsx + 1
   end
   
      
end
DELETE FROM @res WHERE STARTTIME=ENDTIME

return
  

end

create  function [dbo].[DateOnly](@DateTime DateTime)
-- Returns @DateTime at midnight; i.e., it removes the time portion of a DateTime value.
returns datetime
as
    begin
    return dateadd(dd,0, datediff(dd,0,@DateTime))
    end