简体   繁体   English

在 SQL 服务器中转置日期时间记录

[英]Transposing Datetime Records in SQL Server

I'm working with the following table in SQL Server, which captures the start & end date/time for which an employee worked:我正在使用 SQL 服务器中的下表,该表捕获员工工作的开始和结束日期/时间:

EMP_NO  RECORD_DATE     START_TIME          END_TIME
123456  2020-07-04      10:00:00.0000000    14:30:00.0000000

I need to transpose the date/time values, so that it generates incremental records at 30 minute intervals with the Date/time values concatenated:我需要转置日期/时间值,以便它以 30 分钟的间隔生成增量记录,并连接日期/时间值:

Expected Result:预期结果:

EMP_NO  SHIFT_WORKED
123456  2020-07-04 10:00
123456  2020-07-04 10:30
123456  2020-07-04 11:00
123456  2020-07-04 11:30
123456  2020-07-04 12:00
123456  2020-07-04 12:30
123456  2020-07-04 13:00
123456  2020-07-04 13:30
123456  2020-07-04 14:00

Sample code:示例代码:

CREATE TABLE #HOURS (
  EMP_NO INT NOT NULL,
  RECORD_DATE DATETIME ,
  START_TIME TIME NOT NULL, 
  END_TIME TIME   NOT NULL
) 

INSERT INTO #HOURS 
VALUES  (123456  ,' 2020-07-04',' 10:00',' 14:30') 

A tally table will help you here. 计数表将在这里为您提供帮助。 (I prefer to call it an "integers table"). (我更喜欢称它为“整数表”)。 This is just a table of integers.这只是一个整数表。 You can either actually have one persisted somewhere in the database, or create one "one the fly" with a CTE.您可以在数据库中的某个地方实际保存一个,也可以使用 CTE 创建一个“one the fly”。 There are a lot of different ways to create such a thing, some faster than others!有很多不同的方法可以创建这样的东西,有些方法比其他方法更快!

Once you have a tally table, you can generate any values that can be mathematically derived from that.一旦你有了一个计数表,你就可以生成任何可以从数学上推导出来的值。 In your case, datetime values in 30 minute increments.在您的情况下, datetime时间值以 30 分钟为增量。 You can then join that onto your date range.然后,您可以将其加入您的日期范围。 Here's one way which generates a tally table as a CTE这是生成计数表作为 CTE 的一种方法

with integers as (
   select     top 1000 -- as many as you need
              i = -1 + row_number() over (order by a.number) -- start from 0
   from       master..spt_values  a
   cross join master..spt_values  b   
)
select      h.emp_no,
            shift_worked = dateadd(minute, i * 30, t.startdt)
from        #hours   h
cross apply (  -- this cross apply just makes the join to integers easier to read                   
                select startdt = h.record_Date + cast(h.start_Time as datetime),
                       enddt = h.record_date + cast(h.end_time as datetime)
            )        t
join        integers i on dateadd(minute, i * 30, t.startdt) < t.enddt

you can do this:你可以这样做:

    CREATE TABLE temp (EMP_NO  INT ,SHIFT_WORKED datetime)
    DECLARE @START_TIME TIME,@END_TIME TIME,@shift TIME,@emp int
    SELECT @START_TIME=START_TIME,@END_TIME=END_TIME,@emp=EMP_NO FROM #HOURS
    SET @shift=@START_TIME
    WHILE DATEADD(MINUTE, 30, @shift) <=@END_TIME
    BEGIN
    INSERT INTO temp  VALUES(@EMP,@shift)
    SET @Shift = DATEADD(MINUTE, 30, @shift)
    END

    

    
   

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM