I\'ve got a sort of tree like thing going on in my MySQL database.
I have a database that has categories, and each category has a subcat. I\'m keeping all the catego
This thread may help: http://forums.mysql.com/read.php?10,32818,32818#msg-32818
What you really want is START WITH and CONNECT BY syntax, but this is only supported in Oracle, not MySQL.
I'm assuming you know how to get the ID number and that's not the point of the question. Also, parent_id
should also be a FK referencing id
, and I would use NULL for the topmost layer, not 0.
If your top-most categories have at most one level of sub-category, you can use this query to get all Toys:
SELECT *
FROM items
WHERE items.category_id IN (SELECT id FROM categories
WHERE categories.parent_id = 1
OR categories.id = 1);
If your categories can have nested sub-categories, you'll have to use a stored procedure and call it recursively. Pseudocode:
Procedure getItemsInCategory
Input: @category_id integer
Output: items rows
{
For each item in (SELECT *
FROM items
WHERE items.category_id = @category_id):
return the row;
For each id in (SELECT id
FROM categories
WHERE categories.parent_id = @category_id):
return the rows in getItemsInCategory(id);
}
But if I had like 10 categories under Toys, then I'd have to do this join and query 10 times. Is there a better way to handle this?
Yes, there's a way of storing data called "nested sets". It's a bit harder to insert the data, but simple to select an entire, multi-level branch using a single select
statement.
Also, Celko has written a book about this subject, with a chapter about nested sets and other chapters about other methods.
I am not familiar with MySQL, but here is the way I would do it in TSQL (SQL SERVER), maybe try to find an equivalent way of doing it in MySQL?
1) Loop through all categories to get the children for the specific item, in this case categorie id = 1
2) Filter the items to that relating to the children in the Hierarchy CTE(Common Table Expression).
With Hierarchy As
(
SELECT id, name, parent_id
from categories
where id = 1
UNION ALL
SELECT child.id, child.name, child.parent_id
from categories child
inner join Hierarchy parent on child.parent_id = parent.id
)
SELECT * FROM items
WHERE category_id IN
(
Select id
from Hierarchy
)
Assuming you know the id of the Toys category, and nothing is in the top-level Toys category:
SELECT * FROM items WHERE category_id IN (SELECT id FROM categories WHERE parent_id = 1)