2016-10-19 43 views
-3

私はWarehouseStore.dws6.BeScheduleItemというテーブルを持っています。 以下は、WarehouseStore.dws6.BeScheduleItemにあるデータのスクリーンショットです。 WarehouseStore.dws6.BeScheduleItemSQL Serverの再帰的ループ

私の要件は、WarehouseStore.dws6.BeScheduleItemテーブルから欠落しているノードを見つけることです。以下の条件に基づいています。子フィールドは、NOT NULLフィールドをIcpUidたと 親が子の場合

  • 1にISMISSING子の親を設定し、フィールドのNULL をIcpUidている場合は、すべて0

  • にISMISSING設定し

    1. フィールドにはIcpUidフィールドのNULLがあり、 の親にはIcpUidフィールドのNULLがあり、親の子にはIsMissing equal 1があります。 次にch親IsMissingを1に設定します。

    2. 更新する必要がない限り、手順3を繰り返します。

    私は私のSQLコードで3にステップ1を満たすことができましたが、私はこれ以上更新がないかどうかをチェックするためにforループを行う必要があるとして、4段階ではありません。 以下は、私は上記のコードからの再帰ループを構築することができますどのようなアイデアを提案してくださいすることができ、私の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をループする必要がある、それが現在のデータで必要とされない場合がありますが、我々だけではなく、現在のデータ

    答えて

    0

    使用WHILEまたはCURSORすべてのケースをコードしています。例えばCURSOR:

    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

    0

    これは私が探していたコードです。

    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; 
    
    関連する問題