2016-10-05 4 views
4

У меня возникли проблемы с выяснением наиболее логичного способа клонирования категорий родительских/дочерних продуктов для другой компании.Копирование атрибутов родителя и ребенка

Может быть 3 уровня категорий.

ie. Mens Clothing (L1)>Shirt (L2)>Short Sleeve (L3),
(Shirt является родителем Short Sleeve и Mens Clothing является родителем Shirt)

ParentCategoryId это идентификатор категории непосредственно выше.
ParentString - это идентификаторы всех категорий выше, в порядке уровня.

(т. Е. Для продукта L3, это будет идентификатор для L1, затем идентификатор для L2)
Настольная установка, как показано ниже.

CREATE TABLE #Categories 
(
CategoryId INT 
,CompanyId INT 
,ParentCategoryId INT 
,CategoryName VARCHAR(255) 
,ParentString VARCHAR(20) 
) 
INSERT INTO #Categories VALUES 
(123, 12, NULL, 'Mens Clothing',  NULL), 
(124, 12, 123, 'Shirt',   '123-'), 
(125, 12, NULL, 'Womens Clothing', NULL), 
(126, 12, 125, 'Shirt',   '125-'), 
(127, 12, 124, 'Short Sleeve',  '123-124-'), 
(128, 12, NULL, 'Drinks',   NULL), 
(129, 12, 128, 'Water',   '128-') 

Мне нужно скопировать все категории и уровни к CompanyId 13.

+1

Вы можете найти что-то ценное в [this] (http://stackoverflow.com/a/28554667/92546) ответе. – HABO

ответ

0

Это странное решение.

  1. Ставим в КТР все вещи из компании 12

  2. Мы находим MAX идентификатор из этой таблицы, а затем добавить его в ROW_NUMBER(),

  3. Преобразование ParentString в XML,

  4. Выберите, в чем мы нуждаемся,

И получил выход (смотри ниже), который может быть вставлен в Categories таблицу:

DECLARE @id int 

SELECT @id = MAX(CategoryId) FROM #Categories 

;WITH cte AS (
SELECT ROW_NUMBER() OVER (PARTITION BY CompanyId ORDER BY CategoryId) + @id as NewCategoryId, 
     CategoryId as OldCategoryId, 
     CompanyId, 
     ParentCategoryId, 
     CategoryName, 
     CAST('<p>'+REPLACE(STUFF(ParentString,LEN(ParentString),1,''),'-','</p><p>')+'</p>' as xml) parentxml 
FROM #Categories 
WHERE CompanyId = 12 
) 

SELECT c.NewCategoryId, 
     13 as CompanyId, 
     c1.NewCategoryId as NewParentCategoryId, 
     c.CategoryName, 
     (
     SELECT CAST(f.NewCategoryId as nvarchar(max)) +'-' 
     FROM cte f 
     OUTER APPLY (
      SELECT t.c.value('.','int') as xpart 
      FROM c.parentxml.nodes('/p') as t(c) 
     ) x 
     WHERE OldCategoryId = x.xpart 
     FOR XML PATH('') 
     ) as ParentString 
FROM cte c 
LEFT JOIN cte c1 
    ON c1.OldCategoryId = c.ParentCategoryId 

Выход:

NewCategoryId CompanyId NewParentCategoryId CategoryName ParentString 
130    13   NULL    Mens Clothing NULL 
131    13   130     Shirt   130- 
132    13   NULL    Womens Clothing NULL 
133    13   132     Shirt   132- 
134    13   131     Short Sleeve 130-131- 
135    13   NULL    Drinks   NULL 
136    13   135     Water   135- 

EDIT

Если CategoryId столбец является автоинкрементным столбец IDENTITY затем лучше использовать транзакцию и включить IDENTITY_INSERT ВКЛ:

SET IDENTITY_INSERT Categories ON 
BEGIN TRANSACTION 
... 
COMMIT TRANSACTION 
SET IDENTITY_INSERT Categories OFf 
+0

На первый взгляд/тест это выглядит так, как будто это сработает! Будет обновляться, когда я действительно обойдусь, чтобы запустить обновление. Спасибо за помощь! – Doolius

+0

Добавьте информацию о транзакции и идентификационной информации. – gofr1

+0

Вы пробовали это? – gofr1

0

идентификаторов Первого сдвига на максимальном значение.

declare @shift int = (select max(CategoryId) from #Categories); 
-- data for new company 14 
INSERT #Categories(
SELECT @shift + CategoryId, 14 companyId, @shift + ParentCategoryId, CategoryName, NULL as ParentString 
FROM #Categories 
WHERE companyId = 12; 

Затем воссоздайте ParentString для новой компании так, как вы сделали это для оригинальной компании.

1

Просто для удовольствия, если вы хотите играть с XML и глобальным поиском и заменой. В cteMap2 вы увидите, что мы очень конкретны в отношении строк замены. Иногда не нужно, но лучше безопасно, чем жаль. Просто слово осторожности, часть XML чувствительна к регистру в отношении имен полей.

cteMap1 просто создает стандартное отображение на основе максимального значения в #categories (независимо от компании)

cteMap2 генерирует заменить строки, опять же, очень специфического для нет никаких шансов столкновения.

Тогда мы просто применяем Заменяет один проход

Затем мы преобразуем строку в XML, который затем преобразуется в таблицу для потребления (Insert Into ...)

Declare @OldCoID int = 12 
Declare @NewCoID int = 55 

Declare @String varchar(max) = ((Select * from #Categories Where [email protected] For xml raw)) 

;with cteMap1 as (
     Select Old = CategoryID 
       ,New = (Select max(CategoryID) from #Categories) + Row_Number() over (Order By CategoryID) 
     From #Categories 
     Where CompanyID = @OldCoID) 
    , cteMap2 as (
     Select Old=concat('CategoryId="',Old,'"'),New=concat('CategoryId="',New,'"') From cteMap1 
     Union All 
     Select Old=concat('ParentCategoryId="',Old,'"'),New=concat('ParentCategoryId="',New,'"') From cteMap1 
     Union All 
     Select Old=concat('CompanyId="',@OldCoID,'"'),New=concat('CompanyId="',@NewCoID,'"') 
     Union All 
     Select Old=concat(Old,'-'),New=concat(New,'-') From cteMap1 
    ) 
Select @String = Replace(@String,Old,New) From cteMap2 
Declare @XML xml = @String 

Select CategoryId  = xRow.value('@CategoryId[1]','int') 
     ,CompanyId  = xRow.value('@CompanyId[1]','int') 
     ,ParentCategoryId = xRow.value('@ParentCategoryId[1]','int') 
     ,CategoryName  = xRow.value('@CategoryName[1]','varchar(255)') 
     ,ParentString  = xRow.value('@ParentString[1]','varchar(20)') 
From @XML.nodes('/row') As A(xRow) 

Возвращает

CategoryId CompanyId ParentCategoryId CategoryName ParentString 
130   55   NULL    Mens Clothing NULL 
131   55   130     Shirt   130- 
132   55   NULL    Womens Clothing NULL 
133   55   132     Shirt   132- 
134   55   131     Short Sleeve 130-131- 
135   55   NULL    Drinks   NULL 
136   55   135     Water   135- 
+0

Ницца! Также думал об этом подходе, но, наконец, использовал XML только для ParentString. +1. – gofr1

+1

@ gofr1 Спасибо. Некоторые считают, что манипуляция XML/String является злой. Меня, не так много. –

Смежные вопросы