【问题标题】:Recursive Loop in SQL ServerSQL Server 中的递归循环
【发布时间】:2016-10-19 05:51:07
【问题描述】:

我有一个名为 WarehouseStore.dws6.BeScheduleItem 的表。 下面是在 WarehouseStore.dws6.BeScheduleItem 中找到的数据的屏幕截图。 WarehouseStore.dws6.BeScheduleItem

我的要求是根据以下条件从 WarehouseStore.dws6.BeScheduleItem 表中找到缺失的节点。

  1. 将所有 isMissing 设置为 0

  2. 如果子字段具有 IcpUid 字段不为 NULL 并且 父级具有 IcpUid 字段 NULL 然后将子父级 IsMissing 设置为 1。

  3. 如果子字段具有 IcpUid 字段 NULL 并且 父级具有 IcpUid 字段 NULL 并且父级子级具有 IsMissing 等于 1 然后将子父级 IsMissing 设置为 1。

  4. 重复第 3 步,直到没有更多内容需要更新。

我能够在我的 SQL 代码中满足步骤 1 到 3,但没有满足步骤 4,因为我需要执行一个 for 循环来检查是否没有更多更新。 下面是我的 SQL 代码

DECLARE @TEMP TABLE (
Code NVARCHAR(MAX) NOT NULL,
Name NVARCHAR(MAX) NULL,
Level INT NULL,
IsMissing BIT NULL,
ParentCode NVARCHAR(MAX) NULL,
IcpUid NVARCHAR(MAX) NULL
);

INSERT INTO @TEMP(
Code,
Name,
Level,
IsMissing ,
ParentCode ,
IcpUid 
)
SELECT 
Code,
Name,
Level,
IsMissing = 0,
ParentCode, 
IcpUid
FROM WarehouseStore.dws6.BeScheduleItem 
WHERE IsDeleted = 0
;

UPDATE P SET IsMissing = 1
FROM @TEMP C
INNER JOIN @TEMP P ON P.Code = C.ParentCode
WHERE C.IcpUid IS NOT NULL 
AND P.IcpUid IS NULL
;
SELECT 
P.Code,
P.Name,
P.Level,
C.IsMissing ,
C.ParentCode ,
P.IcpUid 
FROM @TEMP P
INNER JOIN @TEMP C ON P.Code = C.ParentCode
WHERE C.IsMissing = 1
AND C.IcpUid IS NULL 
AND P.IcpUid IS NULL
ORDER BY LEVEL

您能否建议我如何从上述代码构建递归循环。 请注意:需要循环第 3 步,当前数据可能不需要它,但我们正在针对所有情况进行编码,而不仅仅是当前数据

【问题讨论】:

    标签: sql-server recursion business-intelligence


    【解决方案1】:

    使用WHILECURSOR。示例光标:

    DECLARE @code VARCHAR(50) DECLARE db_cursor CURSOR FOR SELECT Code FROM WarehouseStore.dws6.BeScheduleItem WHERE IsDeleted = 0

    OPEN db_cursor FETCH NEXT FROM db_cursor INTO @code

    WHILE @@FETCH_STATUS = 0 BEGIN

    UPDATE ... INNER JOIN ... P ON P.Code = @code WHERE C.IcpUid IS NOT NULL AND P.IcpUid IS NULL

    FETCH NEXT FROM db_cursor INTO @name END CLOSE db_cursor DEALLOCATE db_cursor

    【讨论】:

      【解决方案2】:

      这是我正在寻找的代码。

      DECLARE @TMP TABLE
      (
      Code varchar(40),
      Name varchar(120),
      level int,
      ParentCode varchar(40),
      IcpUid varchar(32),
      IsMIssing bit
      );
      DECLARE @NumCount INT = 0;
      INSERT INTO @TMP
      SELECT
          Code,
          Name,
          level,
          ParentCode,
          IcpUid,
          IsMissing
      FROM WarehouseStore.dws6.BeScheduleItem
      WHERE isdeleted = 0
      AND name not like '%DELETED%';
      --Step 2
      MERGE INTO @TMP TGT USING (
      SELECT DISTINCT 
         P.Code,
         IsMissing = 1
      FROM @TMP C
      INNER JOIN @TMP P ON P.Code = C.ParentCode
      WHERE C.IcpUid IS NOT NULL
      AND P.IcpUid IS NULL
      ) SRC
      ON TGT.Code = SRC.Code
      WHEN MATCHED THEN UPDATE SET TGT.IsMissing = SRC.IsMissing;
      --Step 3
      SET @NumCount = (SELECT COUNT(DISTINCT P.Code)
      FROM @TMP C
      INNER JOIN @TMP P on P.Code = C.ParentCode
      WHERE C.IcpUid IS NULL 
      AND P.IcpUid IS NULL 
      AND C.IsMIssing = 1
        AND C.IsMissing <> P.IsMissing);
      WHILE (@NumCount > 0)
      BEGIN
      --loop
      MERGE INTO @TMP TGT USING (
      SELECT DISTINCT 
      P.Code,
      IsMissing = 1
      FROM @TMP C
      INNER JOIN @TMP P ON P.Code = C.ParentCode
      WHERE C.IcpUid IS NULL 
      AND P.IcpUid IS NULL 
      AND C.IsMIssing = 1
      AND C.IsMissing <> P.IsMissing
      ) SRC
      ON TGT.Code = SRC.Code
      WHEN MATCHED THEN UPDATE SET TGT.IsMissing = SRC.IsMissing;
      SET @NumCount = (SELECT COUNT(DISTINCT P.Code)
      FROM @TMP C
      INNER JOIN @TMP P on P.Code = C.ParentCode
      WHERE C.IcpUid IS NULL 
      AND P.IcpUid IS NULL 
      AND C.IsMIssing = 1 
        AND C.IsMissing <> P.IsMissing );
      END --end loop
      
      SELECT *
      FROM @TMP C
      WHERE IsMissing = 1
      ORDER BY Level;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-22
        • 1970-01-01
        • 2020-02-08
        • 2023-03-29
        • 2019-10-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多