Inner join within table - mysql

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.

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

Count rows in table with certain value in other table

I need a quick way to find the Number of items in a table. The items are linked to an other table. Table 1 is products and table 2 is orders.
Orders contains a paid status (1 or 0).
Orders table example:
id paid
1 0
2 1
Products table example:
id orderid type
1 1 5
2 1 5
3 1 3
4 2 5
5 2 5
6 2 3
Products contains a id (orderid) that refers to the order and a type. So i need the number of products where type = 5 and paid = 1 in the orders table.
What is the best and fastest way to archieve this?
So I need all the paid products with type 5. The result should be '2'.
you can use join like this,
SELECT COUNT(*) AS num_rows
FROM products
LEFT JOIN orders ON orders.id = products.orderid
WHERE type = 5 AND paid = 1
One way is to use a join statement. Making some assumptions about your schema, the following should work:
SELECT COUNT(p.`id`) FROM `products_table` p
LEFT JOIN `orders_table` o ON p.`orderid` = o.`id`
WHERE o.`paid` = 1
AND p.`type` = 5

MySQL: relational division - use case

Can't seem to puzzle different kind of information together to get what I want so here goes..
Three different tables:
Entities
id name
1 A
2 B
3 C
Tags
id name
1 tag_1
2 tag_2
3 tag_3
Users
id name
1 user_1
2 user_2
Both Entities:Tags and Users:Tags are 1:n relationships with both entities and users having any number of tags. There are two tables to handle those relations; entities_tags and users_tags. For example:
entities_tags
entity_id tag_id
1 1
1 2
2 1
2 2
2 3
3 1
users_tags
user_id tag_id
1 1
1 2
Now, given a user, I'd like to fetch all entities for which its tags are all included in the users tags. In my example user_1 should fetch entities A and C. I can fetch the user tags separately if needed, as shown below.
I've tried
SELECT entities.*
(SELECT GROUP_CONCAT(entities_tags.name SEPARATOR ', ')) AS tags
FROM entities
LEFT OUTER JOIN entities_tags ON entities_tags.entity_id = entities.id
LEFT OUTER JOIN tags ON tags.id = entities_tags.tag_id
WHERE tags.name IN ('tag_1','tag_2')
GROUP BY entities.id
HAVING COUNT(tags.name) = 2
But this would only give me both A and B and not C. I shouldn't get B, but I should get C.

MySQL Get Parent With Child Rows Together

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);

Count Memberships of User in Groups

I've a tree structure of an association which is divided in divisions, subdivisions etc. on every level users may have memberships to certain roles.
I want to count the memberships on every "structure type" (association, division, subdivision) as defined in the table
The Table structure looks like:
table intern_structures
Contains the hierarchy (nested set, but that does not matter here)
id | intern_structure_type_id | name | parent_id | lft | rgt
1 1 My Company USA 0 1 6
2 2 Texas 1 2 5
3 3 El Paso 2 3 4
table intern_structure_types
Contains Description to the types like "association", "division", "subdivision"
id | name
1 Association
2 Division
3 Subdivision
table memberships
Contains the memberships
id | user_id | intern_structure_id | role_id
1 1 1 1
2 1 2 2
3 2 3 1
3 2 3 3
....
table roles
Contains role descriptions
id | name
1 Admin
2 Moderator
3 Clerk
I want a grouped list like:
structure_type_name | role_name | count of memberships
Association Admin 1
Association Moderator 10
Association Clerk 0 << !! I miss the zero rows!
Division Admin 7
Divison Moderator 43
Division Clerk 31
Subdivision Admin 234
Subdivision Moderator 942
Subdivision Clerk 456
What I achieved so far is this query:
SELECT
is_types.name,
roles.name,
COUNT(memberships.id)
FROM
roles,
intern_structure_types AS is_types
LEFT JOIN intern_structures AS is_elements ON is_elements.intern_structure_type_id = is_types.id
LEFT JOIN memberships ON memberships.intern_structure_id = is_elements.id
WHERE
roles.id = memberships.role_id
GROUP BY
is_types.id, roles.id
It works fine except that it doesn't list all roles because some roles don't have any memberships yet but I want them listed as well just with 0 as membership count.
I'd be very thankful for any help!
I'm assuming the counts you showed in the OP are contrived. To get the results you want, you should create a derived table of the types and roles in use and then left join that entire query to a cross join of the roles and types.
Select is_types.name
, roles.name
, Count(Z.is_type_name)
From roles
Cross Join intern_structure_types As is_types
Left Join (
Select is_types.name As is_type_name
, roles.name As role_name
From intern_structures As is_elements
Join intern_structure_types As is_types
On is_types.id = is_elements.intern_structure_type_id
Join memberships
On memberships.intern_structure_id = is_elements.id
Join roles
On roles.id = memberships.role_id
) As Z
On Z.is_type_name = is_types.name
And Z.role_name = roles.name
Group By is_types.name, roles.name