sql server—sql函数似乎卡在循环中

to94eoyn  于 2021-08-13  发布在  Java
关注(0)|答案(3)|浏览(442)

我目前正在处理一个函数,它应该在作为参数发送给函数的日期前3个工作日返回。
我对sql中的函数有些陌生,我相信我的逻辑是合理的,但是我被卡住了。
我做了两张table。一个包含所有周末日期,一个包含所有假日日期。该函数的目的是接收一个日期,然后使用2个while循环计算提交日期之前的3个工作日,然后将新日期返回到我的select语句中。
以下是问题中的函数:

FUNCTION [dbo].[lessThreeBD](@WORKING_DT DATE)  
RETURNS DATE   
AS  
BEGIN
DECLARE @ThreeBD DATE
DECLARE @COUNTER INT
SET @COUNTER = 0

WHILE @COUNTER < 4
SET @ThreeBD = @WORKING_DT
BEGIN
    WHILE CASE WHEN (SELECT TOP 1 HOL.DATE from DATABASE.dbo.Holidays HOL where HOL.DATE = CAST(@WORKING_DT AS DATE)) IS NULL THEN 'NOT HOLIDAY' ELSE 'HOLIDAY' END = 'HOLIDAY'
    OR CASE WHEN (SELECT TOP 1 WKND.DATE from DATABASE.dbo.Weekends WKND where WKND.DATE = CAST(@WORKING_DT AS DATE)) IS NULL THEN 'WEEKDAY' ELSE 'WEEKEND' END = 'WEEKEND'
    BEGIN
        SET @WORKING_DT = DATEADD(DAY, -1, @WORKING_DT)
    END
    SET @WORKING_DT = DATEADD(DAY, -1, @WORKING_DT)
    SET @COUNTER  = @COUNTER + 1
SET @ThreeBD = @WORKING_DT
END
RETURN @ThreeBD
END

但是,当我用一个日期测试它时,它似乎被锁定了:
测试线:

SELECT DATABASE.dbo.lessThreeBD('2020-05-24') AS TESTING

这行应该返回20号。
知道我做错什么了吗?
记住假日和周末的餐桌都很好用。我已经测试了case语句,并且得到了每个case语句的预期结果。

zzwlnbp8

zzwlnbp81#

WHILE @COUNTER < 4
SET @ThreeBD = @WORKING_DT

等同于

WHILE @COUNTER < 4
BEGIN
  SET @ThreeBD = @WORKING_DT
END

这是一个无限循环。
在tsql中始终使用begin/end with control flow语句。

WHILE @COUNTER < 4
BEGIN
  SET @ThreeBD = @WORKING_DT
  BEGIN
. . .

也许除了常见的习语,比如

if @@trancount > 0 rollback;
1wnzp6jl

1wnzp6jl2#

我认为问题在于: WHILE @COUNTER < 4 SET @ThreeBD = @WORKING_DT BEGIN 此set命令正在无限循环中执行。

eivgtgni

eivgtgni3#

在修复了null问题和set不在begin中的问题之后,我不得不做了更多的修改,以使这项工作更准确。
最后一个功能如下所示,供任何想自用的人使用:

FUNCTION [dbo].[lessThreeBD](@WORKING_DT DATE)  
RETURNS DATE   
AS  
BEGIN
    DECLARE @COUNTER INT
    SET @COUNTER = 0

    WHILE @COUNTER < 3
    BEGIN
        SET @WORKING_DT = DATEADD(DAY, -1, @WORKING_DT)
        SET @COUNTER  = @COUNTER + 1
        WHILE (SELECT SQL_VARIANT_PROPERTY((SELECT TOP 1 HOL.DATE as CT from crmCAST.dbo.Holidays HOL where HOL.DATE = CAST(@WORKING_DT AS DATE)), 'BaseType')) IS NOT NULL
        OR (((DATEPART(DW, @WORKING_DT) - 1 ) + @@DATEFIRST ) % 7) IN (0,6)
        BEGIN
            SET @WORKING_DT = DATEADD(DAY, -1, @WORKING_DT)
        END
    END
RETURN @WORKING_DT
END

我可以用电脑把周末的table搬走 (((DATEPART(DW, @WORKING_DT) - 1 ) + @@DATEFIRST ) % 7) IN (0,6) 这将告诉我,如果日期是一个周末,所以你唯一需要的是一个表,其中列出了你的业务观察假期,这样你就可以有一个准确的3个工作日的回报。

相关问题