【发布时间】:2020-11-28 13:43:45
【问题描述】:
我正在努力实现以下要求:
我有一个带有备件的产品层次结构。这些备件可以在图表中包含其他部件,这些部件可能具有多层深度。
我的目标是编写一个 T-SQL 查询,允许我按表的任何列(在示例产品、价格或 EndOfWarrantyDate 中)进行排序,但保持层次结构。换句话说,我只想订购父母的物品,而不用担心孩子应该只跟随父母来玩耍。
在下面的示例中,如果您注意到,绿色行按“EndOfWarrantyDate”排序,但我仍然想在其父项旁边显示子项和子项(我不关心对子项进行排序,如只要尊重层次结构)。
注意:上表中的 Id 只是为了更好地识别层次结构,在 db 中我有一个普通的标识列作为 Id。
而且,如果可能的话,我想在单个 SQL 查询中执行此操作,而不必先收集父项、对其进行排序然后获取相关的子项和子项。
我现在的 CTE 看起来像这样,但我不知道如何实现排序。尝试使用 PARTITION,但不知道如何正确应用它来解决我的问题。
WITH
cteProducts (Id, Product, ParentProductId, Price, EndOfWarrantyDate, Depth, RootId)
AS
(
-->>>>>>>>>>Root>>>>>>>>>>>>>>>>>
SELECT Id, Product, ParentProductId, Price, EndOfWarrantyDate, 0 as Depth, Id as RootId
FROM Products
WHERE ParentProductId IS NULL
-->>>>>>>>>>Root>>>>>>>>>>>>>>>>>
UNION ALL
-->>>>>>>>>>Children>>>>>>>>>>>>>>>>>
SELECT e.Id, e.Product, e.ParentProductId, e.Price, e.EndOfWarrantyDate, r.Depth + 1, r.RootId
FROM Products e
INNER JOIN cteProducts r
ON e.ParentProductId = r.Id
-->>>>>>>>>>Children>>>>>>>>>>>>>>>>>
)
SELECT
Id, Product, ParentProductId, Price, EndOfWarrantyDate, Depth, RootId
FROM cteProducts
--ORDER BY RootId, EndOfWarrantyDate
非常感谢任何帮助,谢谢!
【问题讨论】:
-
您可以使用
order by case when @SortColumn = 'Product' then Product when ... end在递归CTE 的anchor 中添加Row_Number()。请注意,所有列都需要转换为兼容类型,例如保修日期需要是一个可排序的字符串:YYYYMMDD。在 CTE 的 recursive 部分中,只需将值传播给孩子。
标签: sql-server tsql common-table-expression