SQL HierarchyId 有时会产生错误的路径
SQL HierarchyId Sometimes Producing Wrong Path
我有一个产品列表,使用 HierarchyId 排序,但对于某些项目,层次结构中向上的完整路径产生了错误的结果。仅针对少数...我将在下面进行演示:
SELECT
ProductId
,Name
,FullName
,Hierarchy
,Hierarchy.ToString() as hierarchyString
,editor.ufn_Product_GetFullName(ProductId) as ufnGetFullName
,Hierarchy.GetLevel() as [level]
FROM Editor.Product
WHERE ProductId = 378
OR Hierarchy.ToString() like '/16/1/1/%'
OR Hierarchy.ToString() = '/16/1/'
OR Hierarchy.ToString() = '/16/'
OR Hierarchy.ToString() = '/'
ORDER BY Hierarchy.ToString()
使用该查询我获得了结果:
它 returns 过程中的大部分路径都很好,生成
'Exterior > Render > Colour > White'
然而其中四个产生最后两个交换项,如
'Exterior > Render > White > Colour'
我这辈子都弄不明白为什么条款会互换,为什么只在某些条款上互换。层次结构看起来是正确的,并且子项的级别都是正确的。我需要你的帮助...
下面是用于从产品层次结构生成路径的函数,但我不明白它怎么可能是问题所在。
ALTER FUNCTION [Editor].[ufn_Product_GetFullName] ( @ID INT )
RETURNS VARCHAR(8000)
AS BEGIN
-- Create and insert names into temp table
DECLARE @NamesTable TABLE (Name varchar(8000));
INSERT @NamesTable (Name)
SELECT t1.Name
FROM ( SELECT ProductId, Hierarchy, Name
FROM Product WITH(NOLOCK)
WHERE (ProductId = @ID)) AS t2
CROSS JOIN Product AS t1
WHERE (t1.Hierarchy = t2.Hierarchy)
OR (t1.Hierarchy <> '/')
AND (t2.Hierarchy.IsDescendantOf(t1.Hierarchy) = 1)
ORDER BY t1.Hierarchy;
-- Define name string
DECLARE @Name VARCHAR(8000);
-- Coalesce names from temp table into one long string
SELECT @Name = COALESCE(@Name + ' > ', '') + Name
FROM @NamesTable
-- Return full string
RETURN @Name
END
没有 ORDER BY
子句,您无法确定行顺序。将列 Level
添加到 @NamesTable
table。将 ORDER BY
子句添加到要连接字符串的 SELECT
中。这应该有所帮助。
ALTER FUNCTION [Editor].[ufn_Product_GetFullName] ( @ID INT )
RETURNS VARCHAR(8000)
AS BEGIN
-- Create and insert names into temp table
DECLARE @NamesTable TABLE (Name varchar(8000), Level int);
INSERT @NamesTable (Name, Level)
SELECT t1.Name, t1.Hierarchy.getLevel()
FROM ( SELECT ProductId, Hierarchy, Name
FROM Product WITH(NOLOCK)
WHERE (ProductId = @ID)) AS t2
CROSS JOIN Product AS t1
WHERE (t1.Hierarchy = t2.Hierarchy)
OR (t1.Hierarchy <> '/')
AND (t2.Hierarchy.IsDescendantOf(t1.Hierarchy) = 1)
ORDER BY t1.Hierarchy;
-- Define name string
DECLARE @Name VARCHAR(8000);
-- Coalesce names from temp table into one long string
SELECT @Name = COALESCE(@Name + ' > ', '') + Name
FROM @NamesTable
ORDER BY Level
-- Return full string
RETURN @Name
END
我有一个产品列表,使用 HierarchyId 排序,但对于某些项目,层次结构中向上的完整路径产生了错误的结果。仅针对少数...我将在下面进行演示:
SELECT
ProductId
,Name
,FullName
,Hierarchy
,Hierarchy.ToString() as hierarchyString
,editor.ufn_Product_GetFullName(ProductId) as ufnGetFullName
,Hierarchy.GetLevel() as [level]
FROM Editor.Product
WHERE ProductId = 378
OR Hierarchy.ToString() like '/16/1/1/%'
OR Hierarchy.ToString() = '/16/1/'
OR Hierarchy.ToString() = '/16/'
OR Hierarchy.ToString() = '/'
ORDER BY Hierarchy.ToString()
使用该查询我获得了结果:
'Exterior > Render > Colour > White'
然而其中四个产生最后两个交换项,如
'Exterior > Render > White > Colour'
我这辈子都弄不明白为什么条款会互换,为什么只在某些条款上互换。层次结构看起来是正确的,并且子项的级别都是正确的。我需要你的帮助...
下面是用于从产品层次结构生成路径的函数,但我不明白它怎么可能是问题所在。
ALTER FUNCTION [Editor].[ufn_Product_GetFullName] ( @ID INT )
RETURNS VARCHAR(8000)
AS BEGIN
-- Create and insert names into temp table
DECLARE @NamesTable TABLE (Name varchar(8000));
INSERT @NamesTable (Name)
SELECT t1.Name
FROM ( SELECT ProductId, Hierarchy, Name
FROM Product WITH(NOLOCK)
WHERE (ProductId = @ID)) AS t2
CROSS JOIN Product AS t1
WHERE (t1.Hierarchy = t2.Hierarchy)
OR (t1.Hierarchy <> '/')
AND (t2.Hierarchy.IsDescendantOf(t1.Hierarchy) = 1)
ORDER BY t1.Hierarchy;
-- Define name string
DECLARE @Name VARCHAR(8000);
-- Coalesce names from temp table into one long string
SELECT @Name = COALESCE(@Name + ' > ', '') + Name
FROM @NamesTable
-- Return full string
RETURN @Name
END
没有 ORDER BY
子句,您无法确定行顺序。将列 Level
添加到 @NamesTable
table。将 ORDER BY
子句添加到要连接字符串的 SELECT
中。这应该有所帮助。
ALTER FUNCTION [Editor].[ufn_Product_GetFullName] ( @ID INT )
RETURNS VARCHAR(8000)
AS BEGIN
-- Create and insert names into temp table
DECLARE @NamesTable TABLE (Name varchar(8000), Level int);
INSERT @NamesTable (Name, Level)
SELECT t1.Name, t1.Hierarchy.getLevel()
FROM ( SELECT ProductId, Hierarchy, Name
FROM Product WITH(NOLOCK)
WHERE (ProductId = @ID)) AS t2
CROSS JOIN Product AS t1
WHERE (t1.Hierarchy = t2.Hierarchy)
OR (t1.Hierarchy <> '/')
AND (t2.Hierarchy.IsDescendantOf(t1.Hierarchy) = 1)
ORDER BY t1.Hierarchy;
-- Define name string
DECLARE @Name VARCHAR(8000);
-- Coalesce names from temp table into one long string
SELECT @Name = COALESCE(@Name + ' > ', '') + Name
FROM @NamesTable
ORDER BY Level
-- Return full string
RETURN @Name
END