It's not particularly efficient, but if what you want to do is effectively "explode" the entire hierarchy and get the results in sequence from parent to leaf, something like this would do it:
WITH CategoryHierarchy AS
(
SELECT
ID, ParentCategoryIdFk, 0 AS Level,
ROW_NUMBER() OVER (ORDER BY ID) AS SubTreeID
FROM Category
WHERE CategoryID IN
(
SELECT pc.CategoryID
FROM Sale s
INNER JOIN Product p
ON p.saleidfk = s.id
INNER JOIN ProductCategory pc
ON pc.productid = p.id
WHERE s.id = @SaleID
)
UNION ALL
SELECT c.ID, c.ParentCategoryIdFk, h.Level + 1, h.SubTreeID
FROM CategoryHierarchy h
INNER JOIN Category c
ON c.ID = h.ParentID
)
SELECT c.ID, c.ParentCategoryIdFk AS ParentID, c.Name
FROM CategoryHierarchy h
INNER JOIN Category c
ON c.ID = h.ID
ORDER BY h.SubTreeID ASC, h.Level DESC
This should get you results similar to the following:
ID | ParentID | Name
---+----------+----------
1 | NULL | Men
2 | 1 | Shoes
3 | 2 | Sport
---+----------+----------
1 | NULL | Men
2 | 1 | Shoes
4 | 2 | Casual
---+----------+----------
1 | NULL | Men
5 | 1 | Watches
---+----------+----------
6 | NULL | Women
10 | 6 | Watches
Of course the actual results won't have separators like that, I've added those to make the meaning of the results clearer.
If you don't want it completely exploded like this, you can use another rownum to only return the first instance of each parent:
WITH CategoryHierarchy AS
(
SELECT
ID, ParentCategoryIdFk, 0 AS Level,
ROW_NUMBER() OVER (ORDER BY ID) AS SubTreeID
FROM Category
WHERE CategoryID IN
(
SELECT pc.CategoryID
FROM Sale s
INNER JOIN Product p
ON p.saleidfk = s.id
INNER JOIN ProductCategory pc
ON pc.productid = p.id
WHERE s.id = @SaleID
)
UNION ALL
SELECT c.ID, c.ParentCategoryIdFk, h.Level + 1, h.SubTreeID
FROM CategoryHierarchy h
INNER JOIN Category c
ON c.ID = h.ParentID
),
Filter_CTE AS
(
SELECT
ID, Level, SubTreeID
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY SubTreeID) AS RowNum
FROM CategoryHierarchy
)
SELECT c.ID, c.ParentCategoryIdFk AS ParentID, c.Name
FROM Filter_CTE f
INNER JOIN Category c
ON c.ID = f.ID
WHERE f.RowNum = 1
ORDER BY f.SubTreeID ASC, f.Level DESC
...will give you results similar to:
ID | ParentID | Name
---+----------+----------
1 | NULL | Men
2 | 1 | Shoes
3 | 2 | Sport
4 | 2 | Casual
5 | 1 | Watches
6 | NULL | Women
10 | 6 | Watches
Note: Be careful with the second version, as it is not necessarily guaranteed to return results in hierarchical order. It just so happens that this version does because the IDs themselves are in hierarchical order. You can get around this limitation, but it would add a lot more complexity to this already-somewhat-complex query.
The second version does guarantee that a master category will always appear before any of its subcategories, which is fine if you plan to build a recursive data structure using a dictionary. It just might not be suitable for faster stack-based tree building or direct-to-user reporting. For those purposes, you would want to use the first version instead.