我有一个包含ScheduledTime列的表,它包含DateTime值;这些是开始的时间 3小时测试。 该列看起来像这样:
SELECT ScheduledTime from Schedule;
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-20 09:14:48.000
2012-03-20 13:14:48.000
2012-03-20 17:14:48.000
2012-03-20 21:14:48.000
2012-04-14 17:13:19.000
2012-04-14 21:13:19.000
2012-04-15 01:13:19.000
2012-04-15 05:13:19.000
2012-04-15 09:13:19.000
2012-04-15 13:13:19.000
2012-04-15 17:13:19.000
2012-04-15 21:13:19.000
2012-04-16 01:13:19.000
2012-04-16 05:13:19.000
2012-04-16 13:13:19.000
2012-04-16 17:13:19.000
2012-04-17 01:13:19.000
2012-04-17 05:13:19.000
2012-04-17 13:13:19.000
2012-04-18 18:29:16.000
2012-04-19 15:48:12.000
2012-04-19 19:10:00.000
2012-04-19 23:47:00.000
2012-04-20 10:27:28.000
2012-04-20 17:27:00.000
上面列出的日期时间值是3小时测试的开始时间。所以我需要获得下一个可用的插槽进行3小时测试。如果它可以在现有测试或currentTime + 1hr内容纳,那将是最好的。
任务是生成一个列(比如SlotsColumn),它保存从ScheduledTime列获得的3小时槽的开始时间,并且SlotsColumn值> {fn Now()}即CurrentTime。
可选是如果它没有任何这样的值,它应该给CurrentTime + 1hr
使用SQL Server 2008。
I have tried this:
WITH rows AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY [ScheduledTime] ) AS rn
FROM [dbo].[Schedule]
WHERE [ScheduledTime] IS NOT NULL
)
SELECT TOP(1)
DATEADD(second,10800, mc.ScheduledTime) AS NextTime
FROM rows mc
JOIN rows mp
ON mc.rn = mp.rn - 1
WHERE (DATEDIFF(SECOND, mc.ScheduledTime, mp.ScheduledTime) - 10800) >= 10800
order by mc.ScheduledTime DESC
查询返回将来一个有效开始时间的列表,仅当它存在时才会返回。
对于上面的示例数据,它返回'2012-04-20 03:47:00.000'这是错误的,因为它不认为在'2012-04-20 17:27:00.000'有另一个测试。它们不应重叠。 期望的输出是:'2012-04-20 12:27:00.000',因为它是在'2012-04-20 10:27:28.000'测试之后和'2012-04-20 17测试之前: 27:00.000',如此完美的插槽进行3小时测试。 对我来说,CurrentTime是'2012-04-20 11:45:23.393'
如果没有这样的有效时间,我如何确保它返回CurrentTime + 1hr?
可以在C#中完成,但尝试SQL查询。
请提供任何帮助/提示。
答案 0 :(得分:1)
DECLARE @now DATETIME2 = '2012-04-20 11:45:23.393'
DECLARE @schedule TABLE
(
ScheduledTime DATETIME2 NOT NULL
)
INSERT
INTO @schedule
VALUES
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-20 09:14:48.000'),
('2012-03-20 13:14:48.000'),
('2012-03-20 17:14:48.000'),
('2012-03-20 21:14:48.000'),
('2012-04-14 17:13:19.000'),
('2012-04-14 21:13:19.000'),
('2012-04-15 01:13:19.000'),
('2012-04-15 05:13:19.000'),
('2012-04-15 09:13:19.000'),
('2012-04-15 13:13:19.000'),
('2012-04-15 17:13:19.000'),
('2012-04-15 21:13:19.000'),
('2012-04-16 01:13:19.000'),
('2012-04-16 05:13:19.000'),
('2012-04-16 13:13:19.000'),
('2012-04-16 17:13:19.000'),
('2012-04-17 01:13:19.000'),
('2012-04-17 05:13:19.000'),
('2012-04-17 13:13:19.000'),
('2012-04-18 18:29:16.000'),
('2012-04-19 15:48:12.000'),
('2012-04-19 19:10:00.000'),
('2012-04-19 23:47:00.000'),
('2012-04-20 10:27:28.000'),
('2012-04-20 17:27:00.000')
SELECT COALESCE
(
(
SELECT TOP 1
DATEADD(hour, 3, scheduledTime)
FROM @schedule s
WHERE s.scheduledTime >= DATEADD(hour, -3, @now)
AND NOT EXISTS
(
SELECT NULL
FROM @schedule sn
WHERE sn.scheduledTime > s.scheduledTime
AND sn.scheduledTime < DATEADD(hour, 6, s.scheduledTime)
)
ORDER BY
scheduledTime
),
DATEADD(hour, 1, @now)
-- This is redundant
)
答案 1 :(得分:0)
终于工作并达到预期结果的查询是:
WITH rows AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY [ScheduledTime] ) AS rn
FROM Schedule
WHERE [ScheduledTime] IS NOT NULL
)
SELECT COALESCE
(
(
SELECT Top 1
DateAdd(SECOND,-10800,mp.ScheduledTime) AS NewNextTime
FROM rows mc
JOIN rows mp
ON mc.rn = mp.rn - 1
WHERE (DATEDIFF(SECOND, mc.ScheduledTime, mp.ScheduledTime) - 10800) >= 10800
And mp.ScheduledTime >= GETDATE()
And DateAdd(SECOND,-10800,mp.ScheduledTime)>= GETDATE()
order by mc.ScheduledTime
),
(
SELECT TOP 1
DATEADD(hour, 3, scheduledTime) AS NewNextTime
FROM Schedule s
WHERE s.scheduledTime >= DATEADD(hour, -3, GetDate())
AND NOT EXISTS
(
SELECT NULL
FROM Schedule sn
WHERE sn.scheduledTime > s.scheduledTime
AND sn.scheduledTime < DATEADD(hour, 6, s.scheduledTime)
)
ORDER BY
scheduledTime
),
(
SELECT TOP 1
DATEADD(SECOND, (3600), GetDate()) AS NewNextTime
)
)
这将返回有效时间,或者在最坏情况下返回上一次测试结束后的时间。
SELECT COALESCE的第一部分,从现有的插槽中返回一个时隙。 SELECT COALESCE的第二部分在所有测试槽的末尾返回一个时隙。 SELECT COALESCE的第三部分,返回CurrentTime + 1hr。
你们所有人的讨论对于达成这个目标非常有帮助。我仍然会寻找更好的建议,现在将使用这个。
P.S。很抱歉发布此解决方案的延迟。