2016-12-06 55 views
2

我有一個表,其中有一個父/子關係,其中每個兒童的ExternalCategoryCode列數據需要連接到父母ExternalCategoryCode使用兒童的記錄數據更新家長記錄的字段(同一張表)

這裏是被破壞一些示例性數據,其中所述父記錄(ID = 96) ExternalCategoryCodeNULL。關係是通過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。就拿近兩年的記錄如下(編號= 100編號= 101)都鏈接到ParentId 97.因爲編號= 97 ParentIdIS NOT NULL,我們應該繼續向上樹,直到我們 找到NULL(最上面的父母)的ParentId的記錄。
  2. 另一個問題是關於最上面的父母的ExternalCategoryCode是否包含重複?下面的例子顯示了M2 *兩次。這很好,因爲我們的業務邏輯類庫會在發現任何內容時過濾出重複項。
  3. 如果一條記錄在其ParentId(即孩子)有一個鏈接有一個NULL 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 
    ---|------------------------------|----------------------|--------- 
    

有表中的其他父/子損壞也是如此。如何:

  1. 腳本這下問題的表和concatentate與孩子 ExternalCategoryCode數據 父記錄ExternalCategoryCode

  2. 列出更新的父記錄。通常使用UPDATED時,這恰恰說明了這樣的事情,因此我想報這個:使用

    (影響1行(S))

張婷婷林:

  • SQL Server
+0

後裔級別有多深?例如,97是96的孩子。但那麼會有一個101是97的孩子嗎?另外,會有兩個孩子的情況有相同的代碼(例如H1),那麼,父代中的代碼是否需要減少這個重複? – DVT

+0

@DVT我將用這些答案編輯問題。 – garfbradaz

+0

編輯以添加。 – garfbradaz

回答

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; 

輸出使用遞歸CTE頂部父分配給每一個孩子。然後使用XML路徑來連接所有CategoryCode

enter image description here

+2

最後一個記錄的ID是98,而在OP中它應該是99 – GuidoG

+0

@GuidoG謝謝,不知道如果我只是複製/粘貼:$ –

+0

@JuanCarlosOropeza:我注意到我張貼並做了一個快速編輯,只顯示你有多快!:) – garfbradaz

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; 
+1

你可以試試這裏。 http://rextester.com/HBG68280 –

+0

更新了代碼。它應該現在運行。謝謝@JuanCarlosOropeza – DVT

+1

發佈rextester? bw ... CONCAT(CONCAT(' - ',t1.Id),' - '))'等於'CONCAT(' - ',t1.Id,' - ')' –

相關問題