我正在制作一个存储过程来检查假日预订应用程序的用户输入日期的天数,显然如果关闭的用户数量大于一次允许关闭的用户数量那么它将抛出一个错误,这个循环工作(我认为),但我已经在其他地方读过你应该尽量避免SQL中的循环所以我正在寻找一些帮助!继承我的存储过程代码:
CREATE PROCEDURE spBusinessRuleValidation
(
@StartDate DATE,
@EndDate DATE,
@EmployeeID INT
)
/****
Name: spdolater
description: checks business rules
****/
AS
BEGIN
DECLARE @JobRoleID INT
DECLARE @MaxJobTypeAllowedOff INT
DECLARE @MaxEmployeesAllowedOff INT
DECLARE @DateCount INT
DECLARE @SameJobRoleOff INT
DECLARE @DateCheck DATE
SET @JobRoleID = (SELECT JobRoleID FROM Employees WHERE @EmployeeID = Employees.ID)
SET @MaxJobTypeAllowedOff = (SELECT MaxEmployeesAllowedOff FROM JobRole WHERE @JobRoleID = JobRole.ID)
SET @MaxEmployeesAllowedOff = 20
SET @DateCheck = @StartDate
SET @EndDate = DATEADD(DAY, 1, @EndDate)
WHILE (@DateCheck <> @EndDate)
BEGIN
SET @DateCount = (SELECT COUNT (@DateCheck) FROM Holidays)
IF @DateCount > @MaxEmployeesAllowedOff
BEGIN
/*error*/
END
SET @SameJobRoleOff = (SELECT COUNT (*) JobRoleID
FROM Employees
RIGHT JOIN Holidays
ON Employees.ID = Holidays.EmployeeID
WHERE @EmployeeID = Employees.ID
AND @DateCheck = Holidays.StartDate)
IF @SameJobRoleOff > @MaxJobTypeAllowedOff
BEGIN
/*error*/
END
SET @DateCheck = DATEADD(DAY, 1, @DateCheck)
END
END
如果您希望我更多地解释代码和逻辑,请询问。
inb4 OP喜欢变量:)
答案 0 :(得分:0)
你是对的,你永远不应该在SQL中使用循环。 SQL使用集合,您必须根据集合来考虑您的问题。
很明显,您在上面列出的代码无法使用且尚未经过测试。它可以用这种方式编写,但速度很慢。
让我们从集合的角度思考解决问题并迭代地解决问题。这样,如果我不了解您的模型或您的业务规则,您将很容易纠正。
通常,您要检查开始日期和结束日期之间的所有日期,以查看是否有任何未通过标准检查的日期。
首先,找到所有这些日期(作为一组),如下所示:
SELECT *
FROM Holidays AS H
WHERE H.Date BETWEEN @startdate and @enddate
查找每天的计数
SELECT count(*) as [takenbydate], H.Date
FROM Holidays AS H
WHERE H.Date BETWEEN @startdate and @enddate
GROUP BY H.Date
或
SELECT Count() OVER (PARTITION BY H.Date) AS C, *
FROM Holidays AS H
WHERE H.Date BETWEEN @startdate and @enddate
现在我们要检查允许的最大值。为此,我们加入到最大允许表,我们也加入到employee表中以获取作业角色信息,据我所知,在max allowed table中没有日期。如果有,那么在join语句中需要另一个AND
子句。
SELECT Count() OVER (PARTITION BY H.Date) AS C, R.MaxEmployeesAllowedOff, H.*
FROM Holidays AS H
JOIN Employees AS E ON E.ID = @EmployeeID
JOIN JobRole AS R ON R.ID = E.JobRoleID
WHERE H.Date BETWEEN @startdate and @enddate
现在我们检查规则
SELECT *
FROM
(
SELECT Count() OVER (PARTITION BY H.Date) AS C, R.MaxEmployeesAllowedOff, H.*
FROM Holidays AS H
JOIN Employees AS E ON E.ID = @EmployeeID
JOIN JobRole AS R ON R.ID = E.JobRoleID
WHERE H.Date BETWEEN @startdate and @enddate
) sub
WHERE MaxEmployeesAllowedOff < C OR C > 20
如果此查询返回任何结果,则表示您遇到问题。
注意,我添加了Holiday的所有字段以供参考,但是最后一个 查询不需要这些列。最终查询的任何结果 会显示应该抛出一个错误,所需要的只是 你提出的规则的前两列。