我有一个客户数据,其中包含候选ID,开始日期只有varchar格式的日期,以及在单独列中以varchar格式与该日期相关联的时间值。
简要说明候选人将在一天中的任何时间点来到学习中心的数据,例如2014年10月20日上午10点。开始日期为20-10-2014,从上午10:00开始,他将根据时间点进行测试。因此,如果时间点是2 HR,那么在中午12:00他将进行测试。如果时间点是8 HR,它将在上午10:00添加,并且基于此,他将在06:00 PM进行测试。当时间点到达00:00时,开始日期需要是下一个日期而不是20-10-2014。
开始日期需要附加时间值,以便当它越过时间00:00时,开始日期需要增加1,即第二天。我已使用下面的代码将开始日期添加到时间
CAST(STARTDATE as datetime)+ CAST(CAST([TIME],3,0,':')作为时间(0))作为日期时间)为[EXPECTEDDATETIME]
通过以上代码我创建了预期的日期时间
由于动态数据,我无法对值进行硬编码。我尝试应用> =和<时间值类似
case when MyTime >= '00:00' and MyTime < '08:10' the Dateadd(day, 1, date)
这很完美,但我担心的是我不能把值放在08:10,因为它不是所有行的常量值。
我提供了我的数据截图和预期日期列供参考。
Candidate StartDate Time Expected DateTime Timepoint
1 20141020 1000 2014-10-20 10:00:00 0 HR
1 20141020 1200 2014-10-20 12:00:00 02 HR
1 20141020 1400 2014-10-20 14:00:00 04 HR
1 20141020 1800 2014-10-20 18:00:00 08 HR
1 20141020 0000 2014-10-21 00:00:00 12 HR
1 20141020 1200 2014-10-21 12:00:00 24 HR
1 20141020 1300 2014-10-21 13:00:00 25 HR
2 20141020 1100 2014-10-20 11:00:00 0 HR
2 20141020 1300 2014-10-20 13:00:00 02 HR
2 20141020 1500 2014-10-20 15:00:00 04 HR
2 20141020 1900 2014-10-20 19:00:00 08 HR
2 20141020 2100 2014-10-20 21:00:00 12 HR
2 20141020 2300 2014-10-20 23:00:00 24 HR
2 20141020 0230 2014-10-21 02:30:00 27 HR
2 20141020 1330 ..............
3 20141026 1530 ...............
3 20141026 2000
3 20141026 0930
3 20141026 1020
3 20141026 1120
有人可以帮我这个请求吗?
答案 0 :(得分:0)
首先,这看起来像坏数据,可能应该首先使用正确的数据类型(日期时间)正确插入。
您可以使用 recursive cte 来完成您的工作。
为了使用您的数据集,我添加了一个用于订购数据的Id列,因为您无法按日期和时间排序,因为您的数据存在每个候选人复制日期的问题分组。
Runnable样本:
-- temp table to hold your data
CREATE TABLE #Temp
(
Id INT ,
Candidate INT ,
MyDate NVARCHAR(10) ,
MyTime NVARCHAR(10)
)
-- insert the dummy data (with added id for ordering)
INSERT INTO #Temp
( Id, Candidate, MyDate, MyTime )
VALUES ( 1, 1, '20141020', '1000' ),
( 2, 1, '20141020', '1200' ),
( 3, 1, '20141020', '1400' ),
( 4, 1, '20141020', '1800' ),
( 5, 1, '20141020', '0000' ),
( 6, 1, '20141020', '1200' ),
( 7, 1, '20141020', '1300' ),
( 8, 2, '20141020', '1100' ),
( 9, 2, '20141020', '1300' ),
( 10, 2, '20141020', '1500' ),
( 11, 2, '20141020', '1900' ),
( 12, 2, '20141020', '2100' ),
( 13, 2, '20141020', '2300' ),
( 14, 2, '20141020', '0230' ),
( 15, 2, '20141020', '1330' ),
( 16, 3, '20141026', '1530' ),
( 17, 3, '20141026', '2000' ),
( 18, 3, '20141026', '0930' ),
( 19, 3, '20141026', '1020' ),
( 20, 3, '20141026', '1120' )
-- insert data into new temp table, converting values to dates and times
SELECT Id ,
Candidate ,
CONVERT(DATE, MyDate) AS MyDate ,
CONVERT(TIME, LEFT(MyTime, 2) + ':' + RIGHT(MyTime, 2)) AS MyTime
INTO #TempFormatted
FROM #Temp
-- recursive cte
;WITH cte
AS (
-- take the first row
SELECT Id ,
Candidate ,
MyDate ,
MyTime
FROM #TempFormatted
WHERE Id = 1
-- add next row (look at join: t.Id = cte.Id + 1)
UNION ALL
SELECT t.Id ,
t.Candidate ,
-- CASE used to compare rows and add a DAY if required
CASE WHEN t.MyTime > cte.MyTime
AND t.Candidate = cte.Candidate
THEN cte.MyDate
WHEN t.MyTime < cte.MyTime
AND t.Candidate = cte.Candidate
THEN DATEADD(DAY, 1, t.MyDate)
ELSE t.MyDate
END AS MyDate ,
t.MyTime
FROM cte
INNER JOIN #TempFormatted t ON t.Id = cte.Id + 1
)
-- output from cte
SELECT cte.Id ,
cte.Candidate ,
cte.MyDate ,
cte.MyTime ,
CONVERT(DATETIME, cte.MyDate) + CONVERT(DATETIME, cte.MyTime) FormattedValue
FROM cte
-- tidy up
DROP TABLE #Temp
DROP TABLE #TempFormatted