我在解决克服其他公司的父/子产品类别最合理的方法时遇到了问题。
可以有3个级别的类别。
即。 Mens Clothing
(L1)> Shirt
(L2)> Short Sleeve
(L3)
(Shirt
是Short Sleeve
的父级,Mens Clothing
是Shirt
的父级。
ParentCategoryId
是上面类别的ID。
ParentString
是以上所有类别的ID,按级别排列。
(即对于L3产品,它将是L1的Id,然后是L2的Id) 表格设置如下。
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。
答案 0 :(得分: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 CompanyId=@OldCoID 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-
答案 1 :(得分:0)
首先按最大值移位ID。
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。
答案 2 :(得分:0)
这是一个奇怪的解决方案。
我们从公司12中输入CTE所有东西,
我们从此表中找到MAX
个ID,然后将其添加到ROW_NUMBER()
,
将ParentString
转换为XML,
选择我们需要的内容,
得到输出(见下文),可插入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-
修改强>
如果CategoryId
列是自动递增的IDENTITY列,那么最好使用事务并将IDENTITY_INSERT
设置为ON:
SET IDENTITY_INSERT Categories ON
BEGIN TRANSACTION
...
COMMIT TRANSACTION
SET IDENTITY_INSERT Categories OFf