the*_*heK 13 schema database-design sql-server
我正在尝试建立一个医生预约系统,在线患者将有两个选择:
约束:
到目前为止我们完成的模型是基于创建一个如下所示的 Doctor Slot 表

如果 DoctorSlot 为 N 且 N=10 分钟,请考虑以下示例
案例 第一次 if(N*2)== Free 保留块两个插槽而不是一个
案例跟进 if(N)==Free Make Reservation Block 1 slot
示例医生:9:00 至 9:10 医生:9:10 至 9:20 医生:9:20 至 9:30
病例首次向患者展示 9:00 至 9:20
挑战:
问题:
我建议使用一个Appointment表格来存储每个医生的当前预约。我们可以在此表上添加一些约束,将约会开始时间限制为甚至十分钟(例如 9.00、9.10、9.20),并添加一些其他常识检查,例如EndTimeafterStartTime和医生不能同时开始两个约会. 假设您还希望医生只在上午 9 点到下午 5 点之间工作,因为每个人都需要一些工作与生活的平衡。
CREATE TABLE Appointment (
DoctorID char(1) NOT NULL,
[Date] date NOT NULL,
StartTime time(0) NOT NULL CONSTRAINT CHK_StartTime_TenMinute CHECK (DATEPART(MINUTE, StartTime)%10 = 0 AND DATEPART(SECOND, StartTime) = 0),
EndTime time(0) NOT NULL CONSTRAINT CHK_EndTime_TenMinute CHECK (DATEPART(MINUTE, EndTime)%10 = 0 AND DATEPART(SECOND, EndTime) = 0),
Status char(1) NOT NULL,
UserID char(1) NOT NULL,
Price int NOT NULL,
CONSTRAINT PK_Appointment PRIMARY KEY CLUSTERED (DoctorID, [Date], StartTime),
CONSTRAINT CHK_StartTime_BusinessHours CHECK (DATEPART(HOUR, StartTime) > = 9 AND DATEPART(HOUR, StartTime) < = 16),
CONSTRAINT CHK_EndTime_BusinessHours CHECK (DATEPART(HOUR, EndTime) > = 9 AND DATEPART(HOUR, DATEADD(SECOND, -1, EndTime)) < = 16),
CONSTRAINT CHK_EndTime_After_StartTime CHECK (EndTime > StartTime));
CREATE INDEX iDoctor_End ON Appointment (DoctorID, [Date], EndTime);
Run Code Online (Sandbox Code Playgroud)
我们可以在这个表中插入一些数据,看看它是什么样子的。请注意,第三次插入将失败,因为它被我们的约束阻止了。医生不能同时预约两次。
INSERT INTO Appointment VALUES ('A', '20170420', '09:00:00', '09:10:00', 'P', '1', '0');
INSERT INTO Appointment VALUES ('A', '20170420', '09:20:00', '09:40:00', 'C', '2', '10');
INSERT INTO Appointment VALUES ('A', '20170420', '09:00:00', '09:20:00', 'C', '2', '10');
Run Code Online (Sandbox Code Playgroud)
假设您有一个数字表。如果你没有很多其他人已经描述了如何创建一个。如果所有其他方法都失败了,这可以为您创建一个,但这可能不是最好的方法。
CREATE TABLE Numbers (Number int PRIMARY KEY CLUSTERED);
DECLARE @number int = 0;
WHILE @number < 1000
BEGIN
INSERT INTO Numbers VALUES (@number);
SET @number += 1;
END
Run Code Online (Sandbox Code Playgroud)
现在,如果我们想查看特定医生的空闲槽位,我们需要做的就是指定哪个医生,以及我们要查找的槽位多长时间:
DECLARE @doctorID char(1) = 'A';
DECLARE @length tinyint = 20;
WITH Slots AS (
SELECT StartTime = DATEADD(MINUTE, ((DATEPART(MINUTE, GETDATE())/10)+1+Number)*10, DATEADD(HOUR, DATEPART(HOUR, GETDATE()), CONVERT(smalldatetime, CONVERT(date, GETDATE())))),
EndTime = DATEADD(MINUTE, @length, DATEADD(MINUTE, ((DATEPART(MINUTE, GETDATE())/10)+1+Number)*10, DATEADD(HOUR, DATEPART(HOUR, GETDATE()), CONVERT(smalldatetime, CONVERT(date, GETDATE())))))
FROM Numbers)
SELECT TOP 15 DoctorID = @doctorID,
s.StartTime,
s.EndTime
FROM Slots AS s
WHERE NOT EXISTS (SELECT 1
FROM Appointment AS a
WHERE (CONVERT(time(0), s.StartTime) < a.EndTime AND CONVERT(time(0), s.EndTime) > a.StartTime)
AND a.DoctorID = @doctorID
AND a.[Date] = CONVERT(date, s.StartTime))
AND DATEPART(HOUR, s.StartTime) >= 9
AND DATEPART(HOUR, DATEADD(MINUTE, -1, s.EndTime)) <= 16
ORDER BY s.StartTime;
Run Code Online (Sandbox Code Playgroud)
这看起来有点尴尬,所以如果有人可以改进日期逻辑,很乐意接受建议。
如果医生想要休息,请将休息时间作为预约输入,并且无法进行预订。
请注意,表约束不强制执行非重叠约会。这是可能的,但它更复杂。如果这是我的系统,我会考虑一些系统(例如触发器)来最终验证该约会在插入时与现有约会不重叠,但这取决于您。