Continuing swalsh’s spirit of contribution, here are a couple of expansions on hierarchal Category lists. The first adds a logical sort to the list based on Category DisplayOrder.
WITH CategoryParents(ChildId, ParentId, Sort, Trail)
AS (
SELECT c.[Id],
c.ParentCategoryId,
CONVERT(varchar(2000), RIGHT('00000' + LTRIM(STR(c.DisplayOrder)), 11) + '|') AS Sort,
c.[Name] AS Trail
FROM dbo.[Category] c
WHERE c.ParentCategoryId = 0 AND c.[Deleted] = 0
UNION ALL
SELECT c.[Id],
c.ParentCategoryId,
CONVERT(varchar(2000), cp.Sort + '|' + RIGHT('00000' + LTRIM(STR(c.DisplayOrder)), 11) + '|') AS Sort,
CAST(cp.[Trail] + '->' + c.[Name] AS NVARCHAR(400)) AS Trail
FROM dbo.[Category] c
JOIN CategoryParents cp ON c.ParentCategoryId = cp.[ChildId]
WHERE c.[Deleted] = 0
)
SELECT *
FROM CategoryParents cp
JOIN dbo.[Category] c ON cp.[ChildId] = c.Id
WHERE c.[Deleted] = 0
ORDER BY cp.Sort
OPTION(MAXRECURSION 15)
;
If you need a list that shows all Category hierarchies for each Product, you can use the results returned by the above Common Table Expression (CTE) in a FOR XML PATH expression which will concatenate child row values into a single row. Here, multiple Category trails for each Product are separated by a semicolon.
;WITH CategoryParents(ChildId, ParentId, Sort, Trail)
AS (
SELECT c.[Id],
c.ParentCategoryId,
CONVERT(varchar(2000), RIGHT('00000' + LTRIM(STR(c.DisplayOrder)), 11) + '|') AS Sort,
c.[Name] AS Trail
FROM dbo.[Category] c
WHERE c.ParentCategoryId = 0 AND c.[Deleted] = 0
UNION ALL
SELECT c.[Id],
c.ParentCategoryId,
CONVERT(varchar(2000), cp.Sort + '|' + RIGHT('00000' + LTRIM(STR(c.DisplayOrder)), 11) + '|') AS Sort,
CAST(cp.[Trail] + '->' + c.[Name] AS NVARCHAR(400)) AS Trail
FROM dbo.[Category] c
JOIN CategoryParents cp ON c.ParentCategoryId = cp.[ChildId]
WHERE c.[Deleted] = 0
)
SELECT TOP 1000 p.[Id] AS ProductId,
p.[Name] AS [Name],
p.[Sku] AS [SKU],
STUFF( ( SELECT '; ' + RTRIM(cp.Trail)
FROM CategoryParents cp
JOIN dbo.[Category] c ON cp.[ChildId] = c.Id
JOIN dbo.[Product_Category_Mapping] pcm ON c.ID = pcm.CategoryId
WHERE pcm.[ProductId] = p.[Id]
ORDER BY cp.Sort
FOR XML PATH(''),
root('Trail'),
type
).value('/Trail[1]', 'VARCHAR(400)'),
1,
2,
''
) AS [CategoryTrail]
FROM [dbo].[Product] p
ORDER BY p.SKU
OPTION(MAXRECURSION 15)