我有一个包含大约10.000个节点的Tree结构 翻译成20多种语言 完全约230.000记录
表中的相关字段为:
LanguageID, CategoryID, ParentCategoryID, CategoryLevel, isLeaf, Expired, TopLevelCategoryID
我需要使用正确的值填充TopLevelCategoryID
,因此CategoryID where CategoryParentID IS NULL --(or where CategoryLevel=1)
对于所有记录
isLeaf=0 and Expired=0 and TopLevelCategoryID is NOT NULL
经过google搜索后我写了这个查询
Declare @LanguageID nvarchar(10)='FR'
;WITH Explode AS
(
SELECT categoryID AS major,
categoryID AS minor,
LanguageIDID,
CAST(CategoryID as nvarchar(max)) AS levels
FROM dbo.Categories
Where LanguageID=@LanguageID
AND CategoryLevel=1
UNION ALL
SELECT MJ.major, MN.categoryID, MN.LanguageID, MJ.levels +','+CAST(MN.CategoryID as nvarchar(max)) levels
FROM Explode AS MJ
JOIN dbo.Categories AS MN ON MJ.minor = MN.ParentCategoryID
WHERE MN.LanguageID=@LanguageID
AND (','+MJ.levels+',' NOT LIKE '%'+CAST(MN.CategoryID as nvarchar(max))+',%')
AND MN.Expired=0
)
Update c set TopLevelCategoryID= e.major
FROM Explode e
JOIN dbo.Categories c ON c.categoryID=e.minor
WHERE c.LanguageID=@LanguageID
AND c.TopLevelCategoryID IS NULL
OPTION (MAXRECURSION 0)
有效,但即使添加了@LanguageID参数
,也非常慢当然效率不高..
我也想知道它是不是更好的递归例程 对于categorylevel = 6到1 您在TopLevelCategoryID中为每个级别放置ParentCategoryID的值 但是我无法管理递归: - (
这里有一些带有1种语言的示例数据(抱歉但不能使用此数据创建sqlfiddle)
CREATE TABLE dbo.Categories (
languageID nvarchar(3) NULL,
CategoryID int NULL,
ParentCategoryID int NULL,
CategoryLevel int NULL,
isLeaf bit NULL,
Expired bit NULL,
TopLevelCategoryID int NULL
)
INSERT INTO
Categories
(
LanguageID,
CategoryID,
ParentCategoryID,
CategoryLevel,
isLeaf,
Expired,
TopLevelCategoryID
)
VALUES
('EN',10,NULL,1,0,0,NULL),
('EN',20,NULL,1,0,0,NULL),
('EN',30,NULL,1,0,0,NULL),
('EN',40,NULL,1,0,0,NULL),
('EN',107,20,2,0,0,NULL),
('EN',112,10,2,0,0,NULL),
('EN',145,20,2,0,0,NULL),
('EN',167,20,2,0,0,NULL),
('EN',182,30,2,0,0,NULL),
('EN',194,20,2,0,0,NULL),
('EN',199,145,3,0,0,NULL),
('EN',214,112,3,0,0,NULL),
('EN',345,182,3,1,0,NULL),
('EN',567,167,3,0,0,NULL),
('EN',682,194,3,0,0,NULL),
('EN',794,145,3,0,0,NULL),
('EN',814,199,4,0,0,NULL),
('EN',823,214,4,0,0,NULL),
('EN',846,214,4,1,0,NULL),
('EN',880,199,4,0,0,NULL),
('EN',896,567,4,1,0,NULL),
('EN',898,682,4,0,0,NULL),
('EN',1104,823,5,1,0,NULL),
('EN',1120,880,5,1,0,NULL),
('EN',1450,814,5,0,0,NULL),
('EN',1670,814,5,1,0,NULL),
('EN',1820,1450,6,0,0,NULL),
('EN',1940,1450,6,0,0,NULL)
有人可以提供一些提示吗?
谢谢!
突发新闻
我尝试了一种不同的方法,更适合我的技能,因此,将TopLevelCategoryID
设置为parentCategoryID
并使用此查询将此值从低CategoryLevel
级别移至最高级别:
DECLARE @cnt int=1
WHILE @cnt < 8
BEGIN
UPDATE c SET TopLevelCategoryID = COALESCE(c2.TopLevelCategoryID,c2.ParentCategoryID)
FROM Categories cat
JOIN Categories c2
ON c.ParentCategoryID=c2.CategoryID
AND c.LanguageID=c2.LanguageID
WHERE c.CategoryLevel=@cnt
AND c.Expired=0
AND c2.Expired=0
SET @cnt = @cnt + 1
END
来自初步测试的似乎有效,但是处理时间从超过4小时传递到不到1秒,虽然它会很好我认为有一些错误:从我看到的,所有树结构都用CTE和递归处理:不能像现在看来那么简单:
有人可以帮忙找到我没有考虑过的错误吗? 谢谢!
答案 0 :(得分:0)
肯定不是每个人的解决方案,但是对于我的具体要求效果很好,虽然既没有使用CTE也没有使用递归,只有重复:实际上需要事先知道重复的最大水平。但优点是,超过200,000条记录只需不到1秒,而开始时发布的CTE +递归解决方案超过250分钟(不是秒!)
DECLARE @cnt int=1
WHILE @cnt < 8
BEGIN
UPDATE c SET TopLevelCategoryID = COALESCE(c2.TopLevelCategoryID,c2.ParentCategoryID)
FROM Categories cat
JOIN Categories c2
ON c.ParentCategoryID=c2.CategoryID
AND c.LanguageID=c2.LanguageID
WHERE c.CategoryLevel=@cnt
AND c.Expired=0
AND c2.Expired=0
SET @cnt = @cnt + 1
END