Reputation: 3240
I have Adjacency list mode structure like that
by this query
SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = 'ELECTRONICS';
getting result like that
but i want to get result like that, there is any option do it
thanks in advance
Upvotes: 3
Views: 162
Reputation: 5894
As a point of interest, because it might be too much work and different from what you have to be an "answer", I would suggest you look into the concept of "Modified Pre Ordered Tree Traversal". There's a great explanation by Gijs Van Tulder.
It will require additional fields on the table to store the hierarchy data, and extra code to maintain that structure, but it can make tree-structures much easier to deal with in a relational database engine.
Basically, as well as the usual parent_id
that we store with trees, we also store a left
and a right
value. When correctly populated, it's then easy to get "all children of node" by simply selecting all nodes where node.left > parent.left
and node.right < parent.right
, regardless of the depth of the nodes.
Upvotes: 1
Reputation: 48139
You'll need a UNION, and I suggest removing the duplicates of entries at their respective levels. Also, no need to include "NULL" values if your intention is to present to users as in web apps...
select L1.Category_ID,
L1.name,
"1" as HierarchyLevel,
count( L2.Category_ID ) as NextLevelCount
from Category L1
LEFT JOIN Category L2
on L1.Category_ID = L2.Parent
where L1.name = "ELECTRONICS"
group by L1.Category_ID
UNION
select L2.Category_ID,
L2.name,
"2" as HierarchyLevel,
count( L3.Category_ID ) as NextLevelCount
from Category L1
JOIN Category L2
on L1.Category_ID = L2.Parent
LEFT JOIN Category L3
on L2.Category_ID = L3.Parent
where L1.name = "ELECTRONICS"
group by L2.Category_ID
UNION
select L3.Category_ID,
L3.name,
"3" as HierarchyLevel,
count( L4.Category_ID ) as NextLevelCount
from Category L1
JOIN Category L2
on L1.Category_ID = L2.Parent
JOIN Category L3
on L2.Category_ID = L3.Parent
LEFT JOIN Category L4
on L3.Category_ID = L4.Parent
where L1.name = "ELECTRONICS"
group by L3.Category_ID
UNION
select L4.Category_ID,
L4.name,
"4" as HierarchyLevel,
1 as NextLevelCount
from Category L1
JOIN Category L2
on L1.Category_ID = L2.Parent
JOIN Category L3
on L2.Category_ID = L3.Parent
JOIN Category L4
on L3.Category_ID = L4.Parent
where L1.name = "ELECTRONICS"
This is obviously fixed to 4 levels but will union them into a single list, but no duplicates as you presented. I also tacked on the hierarchy level just for reference purposes. In order to get the counts at each level, you must do a LEFT JOIN to the next level, otherwise, you'll miss possible items at the level you are trying to retrieve, but the others SHOULD remain as INNER JOINs.
If you are dealing with products, I would think that if not after 4 levels deep they can't find something, there's a bigger problem :)
Upvotes: 1
Reputation: 14941
Unfortunately it's difficult to count the amount of sub-categories of a category with your current setup. Not only is the depth of your menu limited by the amount of LEFT JOIN
's you add, it's also impossible to tell which categories are directly linked to a category more then one level deep.
A excellent solution to this problem is using a nested set
structure for your menu, you can read more here. More explanation how to do this with mysql here.
Upvotes: 1
Reputation: 364
You can do something like this:
SELECT name FROM category WHERE name = 'ELECTRONICS'
UNION
SELECT t2.name FROM t2 INNER JOIN category as t1 ON t2.parent = t1.category_id WHERE t1.name = 'ELECTRONICS'
UNION
SELECT t3.name FROM t3 INNER JOIN category as t1 ON t3.parent = t1.category_id WHERE t1.name = 'ELECTRONICS'
UNION
SELECT t4.name FROM t4 INNER JOIN category as t1 ON t4.parent = t1.category_id WHERE t1.name = 'ELECTRONICS'
Upvotes: 0