I'm not sure I follow all that, but it sounds like you want all immediate children of category 5.
Here's a way to do that:
SELECT child.*
FROM Category parent
JOIN Category child
ON (child.lft BETWEEN parent.lft AND parent.rgt)
LEFT JOIN Category intermediate
ON (intermediate.lft > parent.lft AND intermediate.rgt < parent.rgt
AND child.lft > intermediate.lft AND child.rgt < intermediate.rgt)
WHERE intermediate.CategoryId IS NULL
AND parent.CategoryId = ?;
edit: Okay, I understand now that the solution above is only a part of what you want. You want:
- Direct ancestors of CD players
- "Uncles" of CD players (siblings of ancestors)
- Siblings of CD players
- Children of CD players
Let me work on that for a few minutes.
Here's what I've come up with:
SELECT descendant.*,
(current.lft BETWEEN descendant.lft AND descendant.rgt) AS is_selected,
COUNT(DISTINCT c.CategoryId) AS depth
FROM Category current
JOIN Category selected
ON (current.lft BETWEEN selected.lft AND selected.rgt)
JOIN Category descendant
ON (descendant.lft BETWEEN selected.lft AND selected.rgt)
LEFT JOIN Category intermediate
ON (intermediate.lft > selected.lft AND intermediate.rgt < selected.rgt
AND descendant.lft > intermediate.lft AND descendant.lft < intermediate.rgt)
JOIN Category c
ON (descendant.lft BETWEEN c.lft AND c.rgt)
WHERE intermediate.CategoryId IS NULL
AND current.CategoryId = ?
GROUP BY descendant.CategoryId
ORDER BY depth, descendant.name;
currentis CD playersselectedis ancestors of CD players (electronics, portable electronics, CD players)descendantis any child or grandchild etc. of eachselectedancestorintermediateis a descendant of eachselectedancestor that is also a parent ofdescendant-- there must be none of these, hence theIS NULLrestriction.cis the chain of ancestors fromdescendantback up to the top, for purposes of determining the depth.
I just realized that my solution would also return all descendants of the current node. So if you were currently viewing "portable electronics," the query would return its children, but it would also return the grandchild "flash" which may not be what you want.