这是existing question的扩展,用于创建排序顺序父子层次结构。
如何按字母顺序对表格进行排序,但所有子节点都处于正确的位置? 因此,在为它们分配了正确的排序顺序后,父节点不按字母顺序排列,并且每个子级别都不是。
注意:我使用的实际数据底部没有数字,它们只是为了说明层次结构的级别(例如,piperoni在比萨饼下)
pizza 0.1
piperoni 0.1.4
cheese 0.1.5
extra cheese 0.1.5.7
vegetariana 0.1.6
burger 0.2
coffee 0.3
如何将其更改为此?
burger 0.1
coffee 0.2
pizza 0.3
cheese 0.3.1
extra cheese 0.3.1.1
piperoni 0.3.2
vegetariana 0.3.3
答案 0 :(得分:0)
约翰保罗库克写了一个有用的查询,我本周早些时候实际使用过
简而言之,它使用递归CTE并使用字符串连接来设置排序
;WITH BOMcte(ComponentID, Name, PerAssemblyQty, BOMLevel, ProductAssemblyID, Sort)
AS
(
SELECT b.ComponentID,
CAST(p.Name as nvarchar(100)),
b.PerAssemblyQty,
b.BOMLevel,
b.ProductAssemblyID,
CAST('\' + p.Name as nvarchar(254))
FROM Production.BillOfMaterials AS b
INNER JOIN Production.Product p
on b.ComponentID = p.ProductID
WHERE b.EndDate IS NULL -- only retrieve components still being used
and b.ComponentID = 775 -- specify a component to explode
UNION ALL
SELECT b.ComponentID,
CAST(REPLICATE ('| ' , b.BOMLevel) + p.Name as nvarchar(100)),
b.PerAssemblyQty,
b.BOMLevel,
b.ProductAssemblyID,
CAST(cte.Sort + '\' + p.Name as nvarchar(254))
FROM Production.BillOfMaterials as b
INNER JOIN Production.Product p
on b.ComponentID = p.ProductID
INNER JOIN BOMcte AS cte
ON b.ProductAssemblyID = cte.ComponentID
WHERE b.EndDate IS NULL -- only retrieve components still being used
)
SELECT Name, PerAssemblyQty
FROM BOMcte
ORDER BY Sort;
这就是我实现它的方式
WITH Counts
AS (
SELECT parent_ID ,
COUNT(id) AS cnt
FROM Contact_Heirarchy
WHERE Contact_Heirarchy.Discontinue_Date IS NULL
GROUP BY Parent_Id
),
Employee ( ID, [ParentId], Contact_ID, Name, ImmediateChildren )
AS (
SELECT Company_Heirarchy_ID ,
Contact_Heirarchy.Parent_ID ,
c.contact_ID ,
c.Reporting_Name AS name ,
ISNULL(cn.cnt, 0) AS ImmediateChildren
FROM Contact_Heirarchy
LEFT OUTER JOIN Contact c ON Contact_Heirarchy.contact_ID = c.Contact_ID
LEFT OUTER JOIN Counts cn ON Contact_Heirarchy.Company_Heirarchy_ID = cn.parent_id
WHERE Contact_Heirarchy.Discontinue_Date IS NULL
),
Tree
AS (
SELECT [Id] ,
[ParentId] ,
Contact_ID ,
0 AS [TreeLevel] ,
CAST('\' + ( cast( 999 - ImmediateChildren as varchar(3)) ) + Name AS VARCHAR(1000)) AS Sort ,
CAST(REPLICATE('| ', 0) + Name AS NVARCHAR(100)) Hierarchy ,
ParentNode.ImmediateChildren
FROM Employee AS ParentNode
WHERE ( Contact_ID in(@contactID))
UNION ALL
SELECT ChildNode.[Id] ,
ChildNode.[ParentId] ,
ChildNode.Contact_ID ,
LIT.[TreeLevel] + 1 AS [TreeLevel] ,
CAST(LIT.sort + '\' + (cast( 999 - ChildNode.ImmediateChildren as varchar(3)) ) + Name AS VARCHAR(1000)) AS Sort ,
CAST(REPLICATE('| ', LIT.TreeLevel + 1) + Name AS NVARCHAR(100)),
ChildNode.ImmediateChildren
FROM Employee AS ChildNode
INNER JOIN [Tree] LIT ON ( ChildNode.[ParentId] = LIT.[Id] )
WHERE ( ChildNode.[ParentId] IS NOT NULL )
)
SELECT Tree.* ,
c.Reporting_Name AS Contact
FROM Tree
INNER JOIN Contact c ON Tree.Contact_ID = c.Contact_ID
ORDER BY Tree.Sort