这是我最好的猜测,你想要做什么。 CTE的前两部分实际上只是把事情变成一种类似于FlyingStreudel所建议的形式。理想情况下,您应该更改数据库以匹配该格式,而不是通过CTE执行此操作。这将使这个过程更加简单,并且对数据完整性也更好。
接下来,我只是以小时为单位获得不同的开始时间。如果你不能使用CTE(你没有提到你使用的SQL Server版本),你可以通过加入数字表来实现。
最后,我使用RAND函数和ROW_NUMBER随机抓取其中一个开始时间。你会想为RAND()设置一个好的种子值。
;WITH TimesAsTimes AS
(
SELECT
ScheduleDay,
CAST(SUBSTRING(T1.Time1Start, 1, 2) + ':' + SUBSTRING(T1.Time1Start, 3, 2) AS TIME) AS time_start,
CAST(SUBSTRING(T1.Time1Stop, 1, 2) + ':' + SUBSTRING(T1.Time1Stop, 3, 2) AS TIME) AS time_stop
FROM
tbl1 T1
WHERE
T1.Time1Start IS NOT NULL
UNION ALL
SELECT
ScheduleDay,
CAST(SUBSTRING(T2.Time2Start, 1, 2) + ':' + SUBSTRING(T2.Time2Start, 3, 2) AS TIME) AS time_start,
CAST(SUBSTRING(T2.Time2Stop, 1, 2) + ':' + SUBSTRING(T2.Time2Stop, 3, 2) AS TIME) AS time_stop
FROM
tbl1 T2
WHERE
T2.Time2Start IS NOT NULL
UNION ALL
SELECT
ScheduleDay,
CAST(SUBSTRING(T3.Time3Start, 1, 2) + ':' + SUBSTRING(T3.Time3Start, 3, 2) AS TIME) AS time_start,
CAST(SUBSTRING(T3.Time3Stop, 1, 2) + ':' + SUBSTRING(T3.Time3Stop, 3, 2) AS TIME) AS time_stop
FROM
tbl1 T3
WHERE
T3.Time3Start IS NOT NULL
),
PossibleTimeStarts AS
(
SELECT
ScheduleDay,
time_start,
time_stop
FROM
TimesAsTimes TAT
UNION ALL
SELECT
ScheduleDay,
DATEADD(hh, 1, time_start) AS time_start,
time_stop
FROM
PossibleTimeStarts PTS
WHERE
DATEADD(hh, 1, time_start) <= DATEADD(hh, -1, PTS.time_stop)
),
PossibleTimesWithRowNums AS
(
SELECT
ScheduleDay,
time_start,
ROW_NUMBER() OVER(PARTITION BY ScheduleDay ORDER BY ScheduleDay, time_start) AS row_num,
COUNT(*) OVER(PARTITION BY ScheduleDay) AS num_rows
FROM
PossibleTimeStarts
)
SELECT
*
FROM
PossibleTimesWithRowNums
WHERE
row_num = FLOOR(RAND() * num_rows) + 1
已知哪些输入?也就是说,ClientId知道查询何时运行,ScheduleDay是否已知?时间应该只存在于第一对时间还是任何时间对中?它需要如何随机?也就是说,你有什么理由不能简单地在开始时间加一个小时? – Thomas 2010-07-19 14:31:41
而不是给出一个计划时间的例子,如果你提供了你正在寻找的结果集,那将会更有用。否则,很难帮助你。 – 2010-07-19 14:33:27
Thomas, 查询运行时ClientID和ScheduleDay是已知的。时间可以来自任何时间,我的要求要求它足够随机,以至于无法预测。 Tom H, 查询的结果将是ClientID,并且该时间属于提供给查询的一天中的一对时间。 – DoubleJ92 2010-07-19 14:48:12