使用Child的记录数据(同一表)

时间:2016-12-06 14:05:51

标签: sql sql-server parent-child

我有一个表格,其中有一个父/子关系,其中每个孩子的ExternalCategoryCode列数据需要连接到父母ExternalCategoryCode

以下是一些损坏的示例数据,即父记录(Id = 96) ExternalCategoryCode NULL 。关系是通过ParentId字段:

Id |Name                          |ExternalCategoryCode|ParentId
---|------------------------------|--------------------|--------- 
96 | Health & Personal Development| NULL               | NULL
---|------------------------------|--------------------|---------
97 | Health                       | H1*;H2*            | 96
---|------------------------------|--------------------|---------
98 | Personal Development         | P1;P2;P3*          | 96
---|------------------------------|--------------------|---------
99 | Other Health                 | OH*                | 96
---|------------------------------|--------------------|---------

数据应如下所示:

Id |Name                          |ExternalCategoryCode  |ParentId
---|------------------------------|----------------------|--------- 
96 | Health & Personal Development| H1*;H2*;P1;P2;P3*;OH*| NULL
---|------------------------------|----------------------|---------
97 | Health                       | H1*;H2*              | 96
---|------------------------------|----------------------|---------
98 | Personal Development         | P1;P2;P3*            | 96
---|------------------------------|----------------------|---------
99 | Other Health                 | OH*                  | 96
---|------------------------------|----------------------|---------

编辑:

  1. 后代级别可以是任何级别的深层,但是深层次的孩子 后代需要更新到主要的父母 ExternalCategoryCode。记下下面的最后两条记录( Id = 100 Id = 101 )都链接到ParentId 97.因为 Id = 97 ParentId IS NOT NULL ,我们应该在树上继续,直到我们 查找ParentId为NULL(最顶级父项)的记录。
  2. 另一个问题是,最高父母的ExternalCategoryCode是否包含重复项?以下示例显示M2 *两次。这很好,因为我们的业务逻辑类库在找到任何重复项时会过滤掉重复项。
  3. 如果某条记录在其ParentId(即儿童)中有一个链接,但的字符为ExternalCategoryCode,则可以忽略这些代码。

    Id |Name                          |ExternalCategoryCode  |ParentId
    ---|------------------------------|----------------------|--------- 
    96 | Health & Personal Development| H1*;H2*;P1;P2;P3*;OH*| NULL
       |                              |                      |
       |                              | M1;M2*; M2*;M3*      |
    ---|------------------------------|----------------------|---------
    97 | Health                       | H1*;H2*              | 96
    ---|------------------------------|----------------------|---------
    98 | Personal Development         | P1;P2;P3*            | 96
    ---|------------------------------|----------------------|---------
    99 | Other Health                 | OH*                  | 96
    ---|------------------------------|----------------------|---------
    100| Medicine                     | M1;M2*               | 97
    ---|------------------------------|----------------------|---------
    101| Other Medicine               | M2*;M3*              | 97
    ---|------------------------------|----------------------|---------
    102| Other Medicine 2             | NULL                 | 97
    ---|------------------------------|----------------------|---------
    
  4. 表中还有其他父/子损坏。我如何:

    1. 将此脚本编入到有问题的表格中,并将其连接起来 父记录ExternalCategoryCode与孩子 ExternalCategoryCode数据?

    2. 列出更新的父记录。通常在使用UPDATED时,这只是显示这样的内容,我想报告一下:

      (1行(s)受影响)

    3. Techology Im使用:

      • SQL Server

2 个答案:

答案 0 :(得分:1)

<强> SQL DEMO 首先连接来自同一父代的所有代码,然后更新。

WITH superParent as (
    SELECT [Id], [Id] as [topParent], [Name], [ExternalCategoryCode], [ParentId]
    FROM Table1 t
    WHERE [ParentId] is NULL
    UNION ALL
    SELECT t.[Id], sp.[topParent], t.[Name], t.[ExternalCategoryCode], t.[ParentId]    
    FROM Table1 t
    JOIN superParent sp
      ON sp.[id] = t.[ParentId]
),  
combine as (
    Select distinct ST2.[topParent], 
        (
            Select ST1.[ExternalCategoryCode] + ';' AS [text()]
            From superParent ST1
            Where ST1.[topParent] = ST2.[topParent]
            ORDER BY ST1.[Id]
            For XML PATH ('')
        ) [External]
    From superParent ST2
    WHERE ST2.[ParentId] IS NOT NULL    
)    
UPDATE T
SET T.[ExternalCategoryCode] = C.[External]
FROM Table1 T
JOIN combine C
  ON T.[Id] = c.[topParent];

SELECT *
FROM Table1;

OUTPUT 使用递归cte为每个子项分配顶级父级。然后使用XML PATH连接所有CategoryCode

enter image description here

答案 1 :(得分:1)

这个很难。试试这个。

CREATE TABLE #Table1
    ([Id] int, [Name] varchar(29), [ExternalCategoryCode] nvarchar(max), [ParentId] varchar(4))
;

INSERT INTO #Table1
    ([Id], [Name], [ExternalCategoryCode], [ParentId])
VALUES
    (96, 'Health & Personal Development', NULL, NULL),    
    (97, 'Health', 'H1*;H2*', '96'),
    (98, 'Personal Development', 'P1;P2;P3*', '96'),
    (99, 'Other Health', 'OH*', '96'),
    (100, 'Medicine', 'M1;M2*', '97'),
    (101, 'Other Medicine', 'M2*;M3*', '97'),
    (102, 'Other Medicine 2', NULL, '97')
;

WITH cte AS (
    SELECT
        Id
        , ParentId AS Direct_Parent
        , Id AS Orig_Parent
        , ExternalCategoryCode
    FROM
        #Table1
    WHERE
        ParentId IS NULL

    UNION ALL

    SELECT
        t1.Id
        , t1.ParentId
        , cte.Orig_Parent
        , t1.ExternalCategoryCode
    FROM
        #Table1 t1
        JOIN cte ON t1.ParentId = cte.Id
), tmp1 AS (
    SELECT DISTINCT
        Orig_Parent
        , ExternalCategoryCode
    FROM
        cte
    WHERE
        Id <> Orig_Parent
        AND ExternalCategoryCode IS NOT NULL
), tmp2 AS (  -- If there are too many children, this one might be needed, other wise, just use tmp1 in tmp3 below
    SELECT DISTINCT
        Orig_parent
    FROM
        tmp1
), tmp3 AS (
    SELECT
        tmp2.Orig_Parent,
        (
        SELECT CONCAT(tmp1.ExternalCategoryCode,',')
        FROM
            tmp1
        WHERE
            tmp1.Orig_parent = tmp2.Orig_Parent
        FOR XML PATH(''),type).value('.','NVARCHAR(MAX)')
        AS New_string 
    FROM
        tmp2
)
UPDATE tab
SET ExternalCategoryCode = tmp3.New_string
FROM #Table1 tab JOIN tmp3 ON tab.Id = tmp3.Orig_Parent

SELECT *
FROM
    #Table1;


DROP TABLE #Table1;