MySQL nested set hierarchy with foreign table - mysql

I'm using a nested set in a MySQL table to describe a hierarchy of categories, and an additional table describing products.
Category table;
id
name
left
right
Products table;
id
categoryId
name
How can I retrieve the full path, containing all parent categories, of a product? I.e.:
RootCategory > SubCategory 1 > SubCategory 2 > ... > SubCategory n > Product
Say for example that I want to list all products from SubCategory1 and it's sub categories, and with each given Product I want the full tree path to that product - is this possible?
This is as far as I've got - but the structure is not quite right...
select
parent.`name` as name,
parent.`id` as id,
group_concat(parent.`name` separator '/') as path
from
categories as node,
categories as parent,
(select
inode.`id` as id,
inode.`name` as name
from
categories as inode,
categories as iparent
where
inode.`lft` between iparent.`lft` and iparent.`rgt`
and
iparent.`id`=4 /* The category from which to list products */
order by
inode.`lft`) as sub
where
node.`lft` between parent.`lft` and parent.`rgt`
and
node.`id`=sub.`id`
group by
sub.`id`
order by
node.`lft`

To fetch parents nodes you need only... left/right values of last (SubCategory n) node.
Fetch your product: SELECT ... FROM product p JOIN category c ON c.id = p.category_id WHERE p.id = ?.
Fetch parents: SELECT ... FROM category WHERE leftCol <= {productCategory['left']} AND rightCol >= {productCategory['right']}
That's pretty everthing you need.

Hey, I think I solved it! :D
select
sub.`name` as product,
group_concat(parent.`name` separator ' > ') as name
from
categories as parent,
categories as node,
(select
p.`name` as name,
p.`categoryId` as category
from
categories as node,
categories as parent,
products as p
where
parent.`id`=4 /* The category from which to list products */
and
node.`lft` between parent.`lft` and parent.`rgt`
and
p.`categoryId`=node.`id`) as sub
where
node.`lft` between parent.`lft` and parent.`rgt`
and
node.`id`=sub.`category`
group by
sub.`category`

Related

SQL query for a selection from a table with categories and subcategories

Structure of the Category table:
id
title
parent_id
Structure of the Item table:
id
title
is_active (0 или 1)
category_id
table structure
Tables are associated with the category_id field by a one-to-many relationship. Those. 1 category can have many items.
The two-level hierarchy in the Category table. This defines the main categories and subcategories. Categories are those records in which parent_id = NULL. And subcategories, these are those records in which parent_id = to some id.
One Item can belong to both the main category (where parent_id = null) and the subcategory (child). Item can be active and not active (0 or 1).
You need to make a query and select from the Category table all the main categories (which have parent_id = null) that have active items (is_active = 1) and which have subcategories also with active itemes.
i.e If the child subcategory has items with is_active = 0, then do not display this category.
I could only choose the main categories in which only active items:
SELECT categories.title, count(analyses.id) FROM items
INNER JOIN categories on items.category_id = categories.id
WHERE categories.parent_id IS NULL
AND categories.is_active = 1
GROUP BY analyses.category_id
ORDER BY analyses_categories.title
But with subcategories can not cope anymore, tell me please who has more experience.
It's a little unclear what you are trying to count (just the active items associated with the parent?), but I would use exists to find out which have children with active items as well:
select c.title, count(*)
from categories c
join item i on i.category_id = c.id
where c.parent_id is null and i.is_active = 1 and exists (
select 1
from categories c2
join item i on c2.id = i.category_id
where c2.parent_id = c.id and i.is_active = 1
)
group by c.title

Reading a database diagram

I've been trying to figure out how to get the products that match a certain category id but I have been unable to figure out how to move from category to products.
How would a query that basically selects all products that match a certain category id look?
This should work:
SELECT products.*
FROM products,
product_category
WHERE product_category.categoryid = CATEGORY_ID
AND products.catalogid = product_category.catalogid
Or if you prefer a join:
SELECT products.*
FROM products
INNER JOIN product_category ON products.catalogid = product_category.catalogid
WHERE product_category.categoryid = CATEGORY_ID
Simply replace CATEGORY_ID by the ID of the category you wish to select.
product_category is a link table, joining the tables products and product_category together: it contains the catalogid, referencing the ID of the category, and catalogid, referencing the ID of the product.

How to Select all Category with its specific Parent CategoryName

I am working on an application. where I have a Table:-
Category(Category_ID,CategoryName,Parent,Category_Tag)
In this table Category_ID and Parent of type bigint and CategoryName and Category_Tag are of nvarchar. I want to select all CategoryName from Category table with its Name and Parent Name also. If any Category does not have any Parent then the query should return '-'
I have used following sql query:
SELECT Category_ID, Category_Name, Parent, Category_Tag FROM Category
But dows not getting the desired result.Please help me.
If you need only ONE level parent category then use LEFT JOIN
SELECT a.Category_ID, a.Category_Name, a.Parent, a.Category_Tag,
ISNULL(b.Category_Name,'-') as Parent_Name
FROM Category as a
LEFT JOIN Category as b on (a.Parent=b.Category_ID)
If you want the empty parent to be replaced with '-', use ISNULL
SELECT Category_ID, Category_Name, ISNULL(convert(varchar(20),Parent), '-') as Parent, Category_Tag FROM Category

how i do this sql trick

I have a table in database for categories and sub categories. Its internal structure is:
id int not null primary
name text
subcatfrom int
it contains some of rows for categories and its sub categories. I want "SELECT" sql command to fetch categories and grouping their sub categories after it for every root category as following for example :
-cat1
--subcat1
--subcat2
-cat2
--subcat1
--subcat2
is it possible ?
The original question wants the subcategories on separate rows. Here is one way:
select name
from ((select category as name, 1 as iscat, category as sortorder
from t
) union all
(select tsub.category as name 0 as iscat, t.category as sortorder
from t join
tsub on
on t.subcategory_id = s.category_id
)
) a
where not exists (select 1 from category c where c.subcategory_id = a.sortorder limit 1)
order by sortorder, iscat desc, name
What is this doing? The inner union all is bringing together all categories and subcategories. It is assigning what you want in the table as well as information for sorting. The overall ordering is by "parent" category name.
The where clause is limiting this data to categories that are not the subcategory of anything else -- the top level categories.
I am making the assumptions that-
1. you have just one level of parent child relationship. ie subcategory can't have further sub-category
2. For top level category, value of subcatfrom is 0
SELECT * FROM
(
SELECT NAME AS parent_category_name, '' AS child_category_name FROM categories WHERE subcatfrom = 0
UNION
SELECT b.NAME AS parent_category_name, a.NAME AS child_category_name FROM categories a JOIN categories b ON a.subcatfrom = b.id
) a ORDER BY a.parent_category_name, a.child_category_name;
That's very easy but with this structure
Table: category_id , name , parent_id
Sample Data
category_id name parent_id
1 A 0
2 B 0
3 C 1
4 D 1
This means A is a category which has 2 subcategories C and D. And parent_id 0 means it is a parent category
Now the sql is
SELECT lc.category_id,
lc.name,
rc.subcategories
FROM categories
LEFT JOIN (
SELECT
subcategory_id ,
GROUP_CONCAT(name) AS subcategories
FROM categories) AS rc
ON lc.category_id = rc.parent_id
This will give you the following result
category_id name subcategories
1 A C,D
2 B (null)

Display Parent Count base on the grand-child

i have two tables
Table1 : Categories ,
Columns : id , parent_id , name
Table2 : products ,
Columns : id , product_name , category_id , subcategory_id , sale_wanted
Here is the detail
A category can have multiple subcategories id. Parent id 0 means it s a category and parent id != 0 means it is a subcategory. Now each product is related to a subcategory. I need to display the names of category and total subcategories count related to each category.
sale 0 means the product is for sale and 1 means it is required.
Now i need this.
1.Display all categories and count of subcategories related to each category where the products related to category are for sale.
The problem it is that your structure is recursive.
I think you can search for more informations about intervallic representation.
Well i have found this solution
select
dc.category_id,
dc.name ,
count(ldc.name) as total
from default_category as dc
inner join default_category as ldc on ldc.parent_id= dc.category_id
inner join(select * from default_products where sale_wanted = 1) as dp on dp.subcategory_id = ldc.category_id
where dc.parent_id = 0
group by dc.category_id
This works well.