MySQL Get Parent With Child Rows Together - mysql

i have searched for questions like this and although many are similars, are not answering exact my questions and queries not work.
Assuming we have the following table
id category_name parent_id
------------------------------------
1 test 0
2 test1 0
3 new_cat 1
4 new_catx 2
5 cat5 1
I want an sql query where the output will be like this
id category_name parent_id
------------------------------------
1 test 0
3 new_cat 1
5 cat5 1
2 test1 0
4 new_catx 2
In sort the output query is sorted based on parent_id. The parent_id = 0 is the root category, then child are following, and then again another parent with it's child. etc

This will work for a 1-level tree, i.e. for a tree containing only parents and their children:
SELECT *
FROM mytable
ORDER BY CONCAT(IF(parent_id=0, '', parent_id), id)
Demo here

Ideally you should use a mapping table for this, to make your solution cleanly scalable. Change your original table struct to
id category_name
---------------------
1 test
2 test1
3 new_cat
4 new_catx
5 cat5
...and have a parent mapping table, like so:
id parent_id
---------------------
3 1
4 2
5 1
Then you would simply modify Giorgos Betsos' excellent query to read:
select t.id, t.category_name, p.parent_id
from testtable t left outer join parents p
on t.id = p.id
ORDER BY CONCAT(IF(p.parent_id is null, '', p.parent_id), t.id);

Related

Query check all parents are present

I have two tables :
Item_category:
id
item_id
category_id
1
4
1
2
5
2
3
5
3
And category:
id
parent_id
1
null
2
1
3
2
All items have a category, and in table item_category I should also have rows with parent category. I try to make a query that show me all items where a parent category is missing. In this exemple item_id : 5 - category : 1 is missing, the query in SQL should show this row.
Any ideas?
Thx a lot for your help. Kinda stuck
You can try something like this
SELECT items.* FROM items LEFT JOIN item_category ON item_id = items.id LEFT JOIN category ON category_id = category.id WHERE parent_id IS NULL

Get either the value or null entry on row in SQL

I have four tables, products, priceplans, and two category tables as follows:
products
---------
product_id
a
b
priceplans
---------
priceplan_id
a
b
product_id (can be null)
price
categoryA
---------
a (id)
category_name
categoryB
---------
b (id)
category_name
In the priceplans a and b are category ids in other tables, the combination (a,b,product_id) is unique but product_id can also be null, and the priceplan should then use the general priceplan for the (a,b,null) combination. That is the theory, but it is not working out as well as I had hoped and I havent managed to construct a query to only filter them out.
Example:
products - 3 products, 2 in the same category, one in another category
product_id a b
1 1 1
2 1 1
3 1 2
priceplans - 3 plans,
1 is for the default (a,b)=(1,1) category combination when there is no product_id,
2 is supposed to override the default as we have declared a product_id, and
3 is the default for (a,b)=(1,2) combination
priceplan_id a b product_id price
1 1 1 null 10
2 1 1 2 15
3 1 2 null 12
What I want the outcome to look like when I join products with the priceplans is:
product_id a b priceplan_id price
1 1 1 1 10
2 1 1 2 15
3 1 2 3 12
If for the product with a category combination (a,b)=(1,1) and id=1 i want the priceplan with combination (a,b,1) if it exists, if not i want the (a,b,null) priceplan. Any suggestions?
I finally managed to create the query I was looking for:
select pro.*, pp.* from products pro
left join price_plans pp
on pro.a=pp.a
and pro.b=pp.b
and (pro.product_id=pp.product_id or pp.product_id is null)
left join price_plans pp2
on pro.a=pp2.a
and pro.b=pp2.b
and pp2.product_id =pro.product_id
where pp.product_id <=> pp2.product_id

Inner join within table

I have a table categories with the following fields:
id, content, is_subcategory, topic_id
Here comes an examplatory set of data:
id content is_subcategory reference_id
=============================================
1 Games 0 989898989
2 Xbox 1 1
3 Playstation 1 1
4 Furniture 0 121212121
5 Sofa 1 4
6 Closet 1 4
7 Music 0 989898989
8 Pop 1 7
9 Reggae 1 7
Explanation:
If the category is a subcategory, its reference_id is the id of the parent category. For example, Sofa has 4 as its reference_id as 4 is the id of Furniture.
If the category is a parent category, its reference_id is the id of another table topics. For example, Music is a parent category and has 989898989 as its reference_id which is the id for the topic "entertainment".
How do I achieve that I can select only those subcategories whose parent category has 989898989 as its reference_id?
You can do just like it was 2 different tables:
select * from categories c, categories parent
where c.reference_id=parent.id and parent.reference_id=989898989 and c.is_subcategory = 1
SELECT * FROM category sub, category super WHERE
sub.reference_id = super.id AND super.reference_id = 989898989
AND sub.is_subcategory = 1
Since you alredy figured out that you need a self join for this question I am sure you can understand my solution. If not, just let me know.
Give different aliases and try
SELECT id,content FROM `categories` Child INNER JOIN
`categories` Parent ON Child.`reference_id` = Parent.`id`
WHERE Parent.reference_id=989898989 and Child.is_subcategory = 1
I like to suggest inner join for better perfomance.

SQL : Get child of of an element

I have a MySQL table of following structure.
**Table elements :**
element_id element_name parent_id
1 UIG 0
2 CAM 1
3 IHG 1
4 USR 1
5 DBL 1
6 APD 1
7 RTM 1
8 OCR 2
9 IRT 3
10 ICR 3
11 OCR 2
12 USH 1
13 AML 1
I need to find child elements of a given element.
I made the following query :
SELECT parent_id,GROUP_CONCAT(element_id)
FROM elements
WHERE parent_id='1'
GROUP BY parent_id
which returns,
+-----------+--------------------------+
| parent_id | GROUP_CONCAT(element_id) |
+-----------+--------------------------+
| 1 | 2,3,4,5,6,7,12,13 |
+-----------+--------------------------+
1 row in set (0.00 sec)
While I need also need the childs of element 2 and 3, which should result into
+-----------+------------------------------------+
| parent_id | GROUP_CONCAT(element_id) |
+-----------+------------------------------------+
| 1 | 2,3,4,5,6,7,8,9,10,11,12,13 |
+-----------+------------------------------------+
1 row in set (0.00 sec)
How do I achieve this without procedures and just a query?
You just need to use the in operator on a subquery.
select group_concat(element_id)
from chpr
where parent_id in (
select group_concat(element_id)
from chpr
where parent_id = 1
group by parent_id)
;
** AS per OP's comment the levels are definitely a concern**
However based on the initial sample data and request, here is the SQLFIDDLE DEMO that provides the results as per the question's expected output.
The only change is that one needs to group by both element_id and parent_id the innner most first subquery.
Not a very elegant query at all:
select 1 as parent_id, group_concat(x.element_id)
from (
(select element_id
from chpr
where parent_id in
(select element_id
from chpr
where parent_id = 1
group by element_id, parent_id
))
union all
(select element_id
from chpr
where parent_id = 1
group by element_id, parent_id
)) x
;
Results:
PARENT_ID GROUP_CONCAT(X.ELEMENT_ID)
1 8,9,10,11,2,3,4,5,6,7,12,13
Use an IN () predicate...
SELECT '1' As Parent_Id,GROUP_CONCAT(element_id)
FROM elements
WHERE Parent_Id IN ('1','2','3')
GROUP BY '1';
Some database require the GROUP BY in this scenario others don't but it's fairly good practice to include it even if it is not needed.
Incidentally, I suspect Parent_Id is a numeric of some sort in which case it should really read...
SELECT 1 As Parent_Id,GROUP_CONCAT(element_id)
FROM elements
WHERE Parent_Id IN (1,2,3)
GROUP BY 1;
You could actually exclude the 1 As Parent_Id and GROUP BY 1 completely.
If you can only specify one value use a sub-query...
SELECT GROUP_CONCAT(element_id)
FROM Elements
WHERE Parent_Id IN (SELECT Element_Id
FROM Elements
WHERE Parent_Id = 1)
Take a look at my this question
Finding all parents in mysql table with single query (Recursive Query)
And here is the source for this kind of work.
http://explainextended.com/2009/07/20/hierarchical-data-in-mysql-parents-and-children-in-one-query/

Select rows that match multiple rows in related table

I have three tables:
item
id name etc
--------------------
1 Rex
2 Fido
3 Geoff
category
id name
------------
1 Dogs
2 Humans
3 Mammals
category_item
category_id item_id
--------------------
1 1
3 1
1 2
3 2
2 3
3 3
I also have an array of category ids. I would like to count the number of items that are related to ALL of the categories in the array.
For example...
Category_ids Result
----------------------
1,2 0
2,3 1
1,2,3 0
Pretty sure I'm gonna kick myself when I figure this one out.
Please try query given below..
select count(*) AS Result from (
SELECT count(item_id) FROM category_item
WHERE
category_id in (2 ,3)
GROUP by item_id
HAVING count(*) = 2
) AS temp
In this query put count(*) value equal to total number of category_id for example if you are checking for category_ids 1,2,3 then put having count(*) = 3. In this query let assume you provide category_id 1 and 2 then it will fetch total number of existence of item_id with
I hope this query will helpful for you.
thanks