2016-12-06 4 views
2

У меня есть таблица, в которой есть отношение родителя/ребенка, где каждая из данных столбца данных 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 ParentIdIS NOT NULL, мы должны продолжать до дерева, пока мы найдите запись с ParentId из NULL (Top Most Parent).
  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. Script это вниз таблицы в вопросе и concatentate в родительских записей ExternalCategoryCode с ребенком ExternalCategoryCode данных?

  2. Перечислите обновленные родительские записи.Обычно при использовании UPDATED, это просто показывает, что-то вроде этого, в результате чего я хотел бы сообщить об этом:

    (1 строка (ы) пострадавших)

Techology Im помощью:

  • 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; 

OUTPUT с помощью рекурсивного ОТВ назначить верхнюю родителя к каждому ребенку. Затем с помощью XML PATH, чтобы сцепить все CategoryCode

enter image description here

+2

Идентификатор вашей последней записи - 98, тогда как в OP это должно быть 99 – GuidoG

+0

@GuidoG Спасибо, не знаю, как это произойдет, если я просто скопирую/paste: $ –

+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

Опубликовать рекстестер? btw ... 'CONCAT (CONCAT ('-', t1.Id), '-'))' равно 'CONCAT ('-', t1.Id, '-')' –