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;
current
is CD playersselected
is ancestors of CD players (electronics, portable electronics, CD players)descendant
is any child or grandchild etc. of eachselected
ancestorintermediate
is a descendant of eachselected
ancestor that is also a parent ofdescendant
-- there must be none of these, hence theIS NULL
restriction.c
is the chain of ancestors fromdescendant
back 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.