虽然循环 SQL 没有填充完整的结果

Posted

技术标签:

【中文标题】虽然循环 SQL 没有填充完整的结果【英文标题】:While Loop SQL not populating complete results 【发布时间】:2021-08-09 02:12:18 【问题描述】:

问题:迭代只发生到记录 131 并给出准确的值,之后参数 @ADE_END_DATE 返回一个 NULL 值,为什么会这样?下面是我的代码。

此外,我注意到Leave_Date 列具有NULL 值,并且迭代停止并为参数@ADE_END_DATE 返回NULL 值,其中NULL 值开始。

感谢您的帮助。

BEGIN
    DECLARE @HIREDATEPlus1Yr DATETIME
    DECLARE @ADE_Leave_Date DATETIME
    DECLARE @ADE_End_Date DATETIME
    DECLARE @ADE_Start_Date DATETIME
    DECLARE @DATECAL DATETIME
    DECLARE @i INT
    DECLARE @j INT
    DECLARE @Loop_length INT
    DECLARE @ID VARCHAR(18)

    -- start of loop
    SET @j = 1

    -- Loop length will equal to the list of all ADRs
    SET @Loop_Length = (SELECT COUNT([AD_ID]) 
                        FROM [DS_ADHOC_MOPs].[ADE].[List] 
                        WHERE Status NOT IN ('MANAGER', 'TBH', 'FROZEN'))

    -- Loop through each ADRs
    WHILE (@j <= @Loop_length)
    BEGIN
        -- Loop through each ADRs
        SET @i = 0

        -- Find AD ID
        SET @ID = (SELECT TOP 1 [AD_ID] FROM [DS_ADHOC_MOPs].[ADE].[List] 
                   WHERE [AD_ID] NOT IN (SELECT TOP (@j-1) [AD_ID] 
                                         FROM [DS_ADHOC_MOPs].[ADE].[List] 
                                         WHERE ([AD_ID] IS NOT NULL 
                                           AND Status NOT IN ('MANAGER', 'TBH', 'FROZEN')))) 

        -- Find the start date of the ADR
        SET @ADE_Start_Date = (SELECT TOP 1 [Hire_Date] 
                               FROM [DS_ADHOC_MOPs].[ADE].[List] 
                               WHERE [AD_ID] NOT IN (SELECT TOP (@j-1) [AD_ID] 
                                                     FROM [DS_ADHOC_MOPs].[ADE].[List] 
                                                     WHERE ([AD_ID] IS NOT NULL 
                                                       AND Status NOT IN ('MANAGER', 'TBH', 'FROZEN')))) 

        -- Hire date plus 1 year
        SET @HIREDATEPlus1Yr = DATEADD(YEAR, 1, @ADE_Start_Date)

        --Adding Leave Date
        SET @ADE_Leave_Date = (SELECT TOP 1 [LEAVE_DATE] 
                               FROM [DS_ADHOC_MOPs].[ADE].[List] 
                               WHERE [AD_ID] NOT IN (SELECT TOP (@j-1) [AD_ID] 
                                                     FROM [DS_ADHOC_MOPs].[ADE].[List] 
                                                     WHERE ([AD_ID] IS NOT NULL 
                                                       AND Status NOT IN ('MANAGER', 'TBH', 'FROZEN'))))  

        
     -- Set a temporary variable which will be 1 year from now. Use the Date ADD formulae to start date, if they are leaver before one year then add leave date (Use IF): DONE
     -- Put everything inside the while loop and add opportunity selecting to it. 

    IF  @ADE_Leave_Date IS NULL 
        SET @ADE_End_Date = DATEADD(YEAR, 1, @ADE_Start_Date)
    ELSE IF @HIREDATEPlus1Yr < @ADE_Leave_Date
        SET @ADE_End_Date = DATEADD(YEAR, 1, @ADE_Start_Date)
    ELSE  
        SET @ADE_End_Date = @ADE_Leave_Date
    
    SET @DATECAL = datediff(DAY, @ADE_Start_Date, @ADE_End_Date)
     
    SET @j = @j + 1

    UPDATE #TEMPTABLEEEE 
    SET [@ADE_End_Date] = @ADE_End_Date
    WHERE @ID = AD_ID
END

SELECT * FROM #TEMPTABLEEEE
END

【问题讨论】:

这适用于哪个 RDBMS?请添加标签以指定您使用的是mysqlpostgresqlsql-serveroracle 还是db2 - 或其他完全不同的东西。 它来自 SQL-Server。 【参考方案1】:

我不确定您为什么要使用 WHILE 循环。看起来这段代码可以大大简化。 SQL 是一种基于集合的语言。只要有可能,您应该尝试将您的数据作为一个整体来处理,而不是将其分解为逐行评估。

这能满足您的需要吗?如果表中的每个 AD_ID 有不止一行,则需要获取 MAX() 或 MIN() Hire_Date/LEAVE_DATE。要改进答案,请考虑提供示例数据。

UPDATE t
SET     [@ADE_End_Date] = ed.ADE_EndDate
FROM    #TEMPTABLEEEE AS t
        INNER JOIN (
                        SELECT  AD_ID
                                ,CASE
                                    WHEN LEAVE_DATE IS NULL THEN DATEADD(YEAR,1,Hire_Date)
                                    WHEN DATEADD(YEAR,1,Hire_Date) < LEAVE_DATE THEN  DATEADD(YEAR,1,Hire_Date)
                                    ELSE LEAVE_DATE
                                END AS ADE_EndDate
                        FROM    DS_ADHOC_MOPs.ADE.List
                        WHERE   Status NOT IN ('MANAGER', 'TBH', 'FROZEN')
                    ) AS ed ON t.AD_ID = ed.AD_ID

【讨论】:

以上是关于虽然循环 SQL 没有填充完整的结果的主要内容,如果未能解决你的问题,请参考以下文章

SQL 结果到具有子对象的复杂对象

从 PL/SQL 游标中获取所有结果的任何简单方法?

从 sql 填充微调器并使结果独一无二

C#,winfom,数据库为access.如何把sql查询结果直接保存在数组中?不是通过循环一个值一个值的赋予。

导出SQL运行结果的方法总结

如何从 C# 中的 SQL 查询结果填充类?