我的数据库中有以下表格:
TBL1
PK
客户端ID
ScheduleDay
Time1Start
Time1Stop
Time2Start
Time2Stop
Time3Start
Time3Stop
状态
以下是一些示例数据
ID ClientID ScheduleDay Time1Start Time1Stop Time2Start Time2Stop Time3Start Time3Stop
-- -------- ----------- ---------- --------- ---------- --------- ---------- ---------
1 3 Sunday 0000 0800 1000 1300 NULL NULL
2 3 Monday 0000 2359 NULL NULL NULL NULL
3 3 Tuesday 1000 1200 1330 1700 1900 2200
4 3 Wednesday 0000 0800 NULL NULL NULL NULL
5 3 Thursday 0800 1200 NULL NULL NULL NULL
6 3 Friday 0400 0800 0900 1600 NULL NULL
时间字段是CHAR(4),因为我以军事格式存储时间。
我需要完成的是这个;对于任何给定的ClientID,将一个或多个记录插入到计划表中,记录的时间值在tbl1的时间范围内。例如,在星期二安排ClientID 3,计划的时间可能是1120。
如果需要插入多个记录,则计划的时间不应超过一小时。
感谢任何和所有帮助!
答案 0 :(得分:1)
首先,您可能想尝试类似
的架构tbl_sched_avail
PK id INT
FK client_id INT
day INT (1-7)
avail_start varchar(4)
avail_end varchar(4)
通过这种方式,您不仅限于有限数量的时间范围。
至于检查时间表可用性 -
CREATE PROCEDURE sp_ins_sched
@start_time varchar(4),
@end_time varchar(4),
@client_id INT,
@day INT
AS
BEGIN
DECLARE @can_create BIT
SET @can_create = 0
DECLARE @fence_start INT
DECLARE @fence_end INT
--IS DESIRED TIME WITHIN FENCE FOR CLIENT
DECLARE c CURSOR FOR
SELECT avail_start, avail_end FROM tbl_sched_avail
WHERE client_id = @client_id
AND day = @day
OPEN c
FETCH NEXT FROM c
INTO @fence_start, @fence_end
WHILE @@FETCH_STATUS = 0 AND @can_create = 0
BEGIN
IF @start_time >= @fence_start AND @start_time < @fence_end
AND @end_time > @fence_start AND <= @fence_end
SET @can_create = 1
FETCH NEXT FROM c
INTO @fence_start, @fence_end
END
CLOSE c
DEALLOCATE c
IF @can_create = 1
BEGIN
--insert your schedule here
END
END
就实际插入记录的代码而言,我需要更多地了解数据库中的表。
答案 1 :(得分:1)
这是我对你要做的事情的最好猜测。 CTE的前两部分实际上只是为了让事情变成类似于FlyingStreudel建议的形式。理想情况下,您应该更改数据库以匹配该格式,而不是通过CTE执行此操作。这将使这更加简单,并且对数据完整性也更好。
接下来,我以小时为单位获得不同的开始时间。如果你不能使用CTE(你没有提到你正在使用的SQL Server版本),你可以通过加入Numbers表来实现这一点。
最后,我使用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