Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 我应该在这个存储过程中使用WHILE循环,还是有其他方法可以得到相同的结果?_Sql_Sql Server_Loops_Stored Procedures - Fatal编程技术网

Sql 我应该在这个存储过程中使用WHILE循环,还是有其他方法可以得到相同的结果?

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

我正在创建一个存储过程,以根据用户输入的日期检查假期预订应用程序的天数,显然,如果关闭的用户数大于一次允许关闭的用户数,那么它将抛出一个错误,我认为这个循环是有效的,但我在其他地方读到过,无论如何,您应该避免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 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