SQL将转换时间转换为一小时增量

时间:2015-10-23 21:13:12

标签: sql sql-server sql-server-2012

我正在使用MS SQL Server 2012,我有一个表格,其中列出了包含开始和结束时间的班次。请参阅此处的示例数据,了解它的外观:

    Declare @MyTable as Table   (
        row_index int identity (1,1),
        id varchar(6) not null,
        date varchar(10) not null,
        shift_number int not null,
        shift_start datetime not null,
        shift_stop datetime not null
    )

Insert @MyTable Values ('A', '01-02-2015', 1, '1900-01-01 08:00:00.000', '1900-01-01 10:30:00.000')
Insert @MyTable Values ('A', '01-02-2015', 2, '1900-01-01 11:00:00.000', '1900-01-01 13:30:00.000')

Select * from @MyTable

如您所见,每个班次跨越多个小时。我正在寻找一种方法将其转换成这样的东西:

Declare @MyTable2 as Table
    (
        row_index int identity (1,1),
        id varchar(6) not null,
        date varchar(10) not null,
        shift_number int not null,
        shift_start datetime not null,
        shift_stop datetime not null,
        hour_number int not null,
        hour_start datetime not null,
        hour_stop datetime not null
    )

Insert @MyTable2 Values ('A', '01-02-2015', 1, '1900-01-01 08:00:00.000', '1900-01-01 10:30:00.000', 1, '1900-01-01 08:00:00.000', '1900-01-01 09:00:00.000')
Insert @MyTable2 Values ('A', '01-02-2015', 1, '1900-01-01 08:00:00.000', '1900-01-01 10:30:00.000', 2, '1900-01-01 09:00:00.000', '1900-01-01 10:00:00.000')
Insert @MyTable2 Values ('A', '01-02-2015', 1, '1900-01-01 08:00:00.000', '1900-01-01 10:30:00.000', 3, '1900-01-01 10:00:00.000', '1900-01-01 10:30:00.000')

Insert @MyTable2 Values ('A', '01-02-2015', 2, '1900-01-01 08:00:00.000', '1900-01-01 10:30:00.000', 1, '1900-01-01 11:00:00.000', '1900-01-01 12:00:00.000')
Insert @MyTable2 Values ('A', '01-02-2015', 2, '1900-01-01 08:00:00.000', '1900-01-01 10:30:00.000', 2, '1900-01-01 12:00:00.000', '1900-01-01 13:00:00.000')
Insert @MyTable2 Values ('A', '01-02-2015', 2, '1900-01-01 08:00:00.000', '1900-01-01 10:30:00.000', 3, '1900-01-01 13:00:00.000', '1900-01-01 13:30:00.000')

Select * from @MyTable2

有没有一种简单的方法可以在不使用某些复杂的循环系统的情况下完成此操作?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

我扩展了测试表。试试我的解决方案 评论编辑:2015-10-26

      Declare @MyTable as Table   (
            row_index int identity (1,1),
            id varchar(6) not null,
            date varchar(10) not null,
            shift_number int not null,
            shift_start datetime not null,
            shift_stop datetime not null,
            hourCnt int  -- I added this field
        )


Insert @MyTable Values ('A', '01-02-2015', 1, '1900-01-01 08:00:00.000', '1900-01-01 10:30:00.000',0)
Insert @MyTable Values ('A', '01-02-2015', 2, '1900-01-01 11:00:00.000', '1900-01-01 15:30:00.000',0)
Insert @MyTable Values ('A', '01-02-2015', 3, '1900-01-01 18:00:00.000', '1900-01-01 19:00:00.000',0)
Insert @MyTable Values ('A', '01-02-2015', 4, '1900-01-01 20:00:00.000', '1900-01-01 20:00:00.000',0)
Insert @MyTable Values ('A', '01-02-2015', 5, '1900-01-01 23:00:00.000', '1900-01-02 01:20:00.000',0)


--Select * from @MyTable

----------

-- we can set this inside to MAINpart
-- but this way is more simple for understanding
update @MyTable
set hourCnt = datediff(hour,shift_start,shift_stop)

declare @MaxHourCnt int
select @MaxHourCnt=max(hourCnt)+2 from @MyTable

-- MAINpart
select my.*, fromto.n as hour_number, 
    dateadd(hour, fromto.n-1, my.shift_start) as hour_start,
    dateadd(hour, fromto.n, my.shift_start) as hour_stop
into #MyTable
from @MyTable my
cross join (
        SELECT TOP (@MaxHourCnt) n = ROW_NUMBER() OVER (ORDER BY number)
        FROM [master]..spt_values 
        ORDER BY n
    ) as fromto
where fromto.n<=my.hourCnt+1
   and dateadd(hour, fromto.n-1, my.shift_start)<shift_stop

-- fixing stop values
update #MyTable
set hour_stop=shift_stop
where hour_stop>shift_stop

select * from #MyTable
drop table #MyTable

答案 1 :(得分:0)

您可以使用日历表...或者更确切地说是小时表。

构建一个表格,其中包含您对跟踪感兴趣的每小时,然后使用JOIN BETWEEN建立一个表格。您需要一个CASE表达式,因为您根本不需要几小时就可以根据需要恢复结果:

SELECT a.*
      ,hour_start = hours
      ,hour_end = CASE WHEN DATEADD(hour,1,hours) > shift_stop THEN shift_stop ELSE DATEADD(hour,1,hours) END
FROM Table1 a
LEFT JOIN lkp_hours b
  ON b.hours BETWEEN shift_start AND shift_stop

演示:SQL Fiddle

注意:如果轮班也可以在半小时后开始,那么您需要额外的逻辑,并且在查找中缩短间隔然后过滤掉奇数小时项可能是有意义的。