如何使用递归逻辑来更新SQL表

时间:2016-01-12 01:03:18

标签: sql recursion

我有一张包含以下数据的表格:

A(0)
     F(0)
     B(1)
          H(1)
          D(1)
               E(1)
                    I(1)
C(0)
     G(0)
J(0)
     K(1)
     L(1)
          M(1)

在结构上看起来像这样,在()中的IsTrue值,第二个teir将始终具有IsBranchHead = 1:

Id   ParentId   IsTrue  IsBranchHead   BranchId
------------------------------------------------
A     Null        0          0          Null
B      A          1          1          B
C     Null        0          0          Null
D      B          1          0          B
E      D          1          0          B
F      A          0          1          Null
G      C          0          1          Null
H      B          1          0          B
I      E          1          0          B
J     Null        0          0          Null
K      J          1          1          K
L      J          1          1          L
M      L          1          0          L

当IsTrue = 1时,最终结果表需要将BranchId字段更新为BranchHead的Id,以获得以下结果

function manipulateData(obj){
    var data = Object.keys(obj).map(function(index){
         //Perform the manipulation 
         return obj;
    }

    return data;
}

现在这可以通过循环和一些条件在代码中完成,但我不知道如何在SQL中执行此操作。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

这是SQL server

的解决方案之一

fiddle

-- Data
DECLARE @data TABLE ([Id] varchar(1), [ParentId] varchar(1), [IsTrue] int, [IsBranchHead] int, [BranchId] varchar(1));

INSERT INTO @data
VALUES
    ('A', NULL, 0, 0, NULL),
    ('B', 'A', 1, 1, NULL),
    ('C', NULL, 0, 0, NULL),
    ('D', 'B', 1, 0, NULL),
    ('E', 'D', 1, 0, NULL),
    ('F', 'A', 0, 1, NULL),
    ('G', 'C', 0, 1, NULL),
    ('H', 'B', 1, 0, NULL),
    ('I', 'E', 1, 0, NULL),
    ('J', NULL, 0, 0, NULL),
    ('K', 'J', 1, 1, NULL),
    ('L', 'J', 1, 1, NULL),
    ('M', 'L', 1, 0, NULL)
;

-- Recursive CTE
WITH cte AS
(
    SELECT 
        Id, ParentId, IsTrue, IsBranchHead, 
        CASE WHEN IsTrue = 1 AND IsBranchHead = 1 THEN Id END AS BranchId 
    FROM @data WHERE ParentId IS NULL
    UNION ALL
    SELECT 
        d.Id, d.ParentId, d.IsTrue, d.IsBranchHead, 
        CASE 
            WHEN d.IsTrue = 1 AND d.IsBranchHead = 1 THEN d.Id -- Use Id as BranchId
            WHEN d.IsTrue = 1 THEN cte.BranchId -- Copy parent BranchId
            ELSE d.BranchId -- Update nothing
        END
    FROM cte INNER JOIN @data d ON cte.Id = d.ParentId
)
UPDATE target SET BranchId = cte.BranchId FROM @data target INNER JOIN cte 
ON target.Id = cte.Id 
--SELECT * FROM cte
--ORDER BY Id

SELECT * FROM @data