Sql 我应该在这个存储过程中使用WHILE循环,还是有其他方法可以得到相同的结果?
我正在创建一个存储过程,以根据用户输入的日期检查假期预订应用程序的天数,显然,如果关闭的用户数大于一次允许关闭的用户数,那么它将抛出一个错误,我认为这个循环是有效的,但我在其他地方读到过,无论如何,您应该避免SQL中的循环,所以我正在寻求一些帮助!这是我的存储过程代码:Sql 我应该在这个存储过程中使用WHILE循环,还是有其他方法可以得到相同的结果?,sql,sql-server,loops,stored-procedures,Sql,Sql Server,Loops,Stored Procedures,我正在创建一个存储过程,以根据用户输入的日期检查假期预订应用程序的天数,显然,如果关闭的用户数大于一次允许关闭的用户数,那么它将抛出一个错误,我认为这个循环是有效的,但我在其他地方读到过,无论如何,您应该避免SQL中的循环,所以我正在寻求一些帮助!这是我的存储过程代码: CREATE PROCEDURE spBusinessRuleValidation ( @StartDate DATE, @EndDate DATE, @EmployeeID INT ) /**** Name: spdola
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 loves variables:如果您是正确的,您不应该在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
或
现在我们要检查允许的最大值。为此,我们加入到允许的最大值表中,我们也加入到employee表中以获取职务角色信息,据我所知,允许的最大值表中没有日期。如果有,那么在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中的所有字段以获取信息,但最终
查询不需要这些列。最终查询的任何结果
将显示应该抛出一个错误,所需的只是
显示规则时规则的前两列
我们都喜欢变量。所以我们喜欢OP,这能做什么?选择COUNT@StartDate FROM Holiday统计假期表中具有相同开始日期的假期数,如果超过20,则将自动不允许预订,它应该是DateCheck,但我只是忘记了我的错误:P-编辑,因此它现在是DateCheck,而不是StartDate@ypercubeNo,它将统计Holidays表中的所有行,只要count中的内容不为null,并且无论其中有什么内容。你可能想从假期中选择COUNT*,其中somecolumn=@DateCheck我想这就是我的意思,这是一个漫长的一天哈哈,谢谢:@ypercubi我对SQL比较陌生,所以我会问很多问题,从H开始。Date,我发现很难理解这将是我的假期表中的哪一列,我的列名是ID、EmployeeID、StartDate、EndDAte、Duration、Status和Reason,我不知道应该是哪个,哈哈@hogan@Jimmy_Chong-这是一个很难解决的问题-实际上,您有多个重叠范围,并且您希望按天计算交点。我现在没有时间写一个解决方案,但也许知道你的问题空间是什么可以帮助你编辑问题,让它更清楚。
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