sql - 虽然循环 SQL 没有填充完整的结果
问题描述
问题:迭代只发生到记录 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
解决方案
我不确定你为什么使用 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
推荐阅读
- msbuild - 每次构建都具有持久唯一的 AssemblyName
- c# - LINQ 合并 2 个列表,保持序列和来源
- python - Django update_or_create 如果值相等则通过
- javascript - 使用 Gulp 连接和缩小后删除生成的 CSS 文件
- c++ - 如何停止在共享库中实现的阻塞 pthread_join()
- python - 匹配以逗号分隔的精确长度的所有单词
- python - 我如何正确处理多维 numpy 数组
- java - Java CriteriaBuilder:传递的类型 CriteriaBuilder.In 不适用于参数
- youtube - 在不阻止谷歌驱动器的情况下阻止 youtube
- c++ - 尝试在另一个 SDL2 上显示一个图像没有错误,但第二个图像不会显示