【发布时间】:2016-06-08 06:53:06
【问题描述】:
我有一个包含大约 10.000 个节点的树结构 翻译成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
在谷歌上搜索了很多之后,我写了这个查询
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 和递归处理的:不可能像我现在看起来那么简单:
有人可以帮我找出我没有考虑和做错的东西吗? 谢谢!
【问题讨论】:
-
这看起来像是一次性工作,所以您可能不需要浪费时间优化它。因此,它不会很快:
(','+MJ.levels+',' NOT LIKE '%'+CAST(MN.CategoryID as nvarchar(max))+',%')实际上你在like中失去了领先的“,”。 -
我不太了解那个过滤器。
MJ.minor = MN.ParentCategoryID是否有很多重复项,我的意思是每个类别可能会出现在不同的级别上? -
能否请您提供示例数据。您的查询对我来说有点模糊:) 递归部分似乎是类别表。不知何故,您还可以将其与 Explode 表连接起来。我确定这部分会降低性能。实际上,您正在将类别加入其上层的 parent_category。在类别表上运行递归查询后,您可以加入 Explode。然后也许你可以将它加入到探索表中。
-
嗨!实际上,它不是一次性工作,而是每周工作,因为每周都会添加一些类别,而另一些类别会被删除。是的,我在复制时丢失了前导“,”。
MJ.minor=MN.CategoryParentID'应该' 将 CTE 的 categoryID 与类别表的 ParentCategoryID 加入 -
@Eralper 当然!刚刚添加
标签: sql-server tree