Multiple table JOIN issue - mysql

first, you should know that i suck big time at SQL.
Here is my problem:
I have 4 tables that i need to be joinned (for usage in SphinxSearch), here is the rough structure:
Accounts
Id Name Category
----------------
1 Test 1
2 Foo 2
3 Bar 1
Category
Id Name
-------
1 Restaurants
2 Store
Accounts_has_subcategory
account_id subcat_id
--------------------
1 1
1 3
2 2
Subcategory
Id Name
-------
1 Chinese
2 Sportswear
3 Delivery
What i want is a resultset looking like this:
accounts.id | accounts.name | category_name | subcategories
-----------------------------------------------------------
1 Test Restaurants Chinese, Delivery
2 Foo Store Sportswear
Right my query looks like this:
SELECT a.id, a.name, c.name as category, group_concat(subcat.name) as subcategories
FROM accounts AS a
JOIN (account_has_subcategory AS ahs, subcategory AS subcat)
ON (a.id = ahs.account_id AND ahs.subcat_id = subcat.id),
accounts AS a2
JOIN category AS c
ON a2.category = c.id
Like said before, i suck at SQL (as soon as it involves multiple joins or stuff like that basically...). If someone could point me in the right direction or offer a solution (with basic explanation, so i can try and get that in my brain -_-), that would make my day since i've been fighting that query for a good 5h now...
Thanks.

Try this?
SELECT a.id, a.name,
c.name as category,
group_concat(subcat.name) as subcategories
FROM accounts AS a
INNER JOIN account_has_subcategory AS ahs ON a.id = ahs.account_id
INNER JOIN subcategory AS subcat ON subcat.id = ahs.subcat_id
INNER JOIN category AS c ON a.category = c.id
GROUP BY a.id, a.name, c.name
ORDER BY a.id;

You're almost there - you just need to fix up your syntax a little and add a group by.
select a.id, a.name, c.name as category, group_concat(subcat.name) as subcategories
from accounts as a
inner join category as c on a.category = c.id
inner join accounts_has_subcategory as ahs on a.id = ahs.account_id
inner join subcategory as subcat on ahs.subcat_id = subcat.id
group by a.id, a.name, c.name

Related

find records grouped by two columns in mysql

I want to find out all seller who have uploaded products in categories (electronics,clothing,furniture), so for 3 categories there can be 3 row against each seller . tables I have are
1.category{category_id,name},
2.seller {seller_id,username},
3.products{product_id,seller_id,category_id,title}
Note:There can be maximum 3 result (coz I'm searching in 3 categories) against one seller even if he added more than one product in single category
expected result:
**product_id** **category** **sellerUsername**
101 electronics kuldeep
211 furniture kuldeep
322 clothing kuldeep
167 electronics roman
245 furniture roman
247 clothing dangi
246 furniture dangi
..
..
if you need only the matching relation use inner join
select a.product_id, b.username, c.name
from products as a
inner join seller as b on b.seller_id = a.seller_id
inner join category as c on c.category_id = a.category_id
else use left join
select a.product_id, b.username, c.name
from products as a
left join seller as b on b.seller_id = a.seller_id
left join category as c on c.category_id = a.category_id
The general solution to your problem is to join the three tables together and then aggregate by seller and category. In my solution, I have arbitraily chosen the max product ID, in the absence of any logic for doing otherwise. The query is slightly tricky, in that we need to additionally join this result again to the category and seller tables to get the human readable category and seller names. The reason for this is the GROUP BY query should ideally be done by ID and not name, since conceivably two categories (or sellers) could have the same name but have different IDs.
SELECT t3.product_id,
COALESCE(t1.name, 'NA'),
COALESCE(t2.username, 'NA')
FROM
(
SELECT MAX(p.product_id) AS product_id,
c.category_id,
s.seller_id
FROM products p
LEFT JOIN category c
ON p.category_id = c.category_id
LEFT JOIN seller s
ON p.seller_id = s.seller_id
WHERE c.name IN ('electronics', 'clothing', 'furniture')
GROUP BY s.seller_id,
c.category_id
) t1
LEFT JOIN category t2
ON t1.category_id = t2.category_id
LEFT JOIN seller t3
ON t1.seller_id = t3.seller_id
Check Below Code.
SET #row_number:=0;
SET #db_names:= '';
SET #db_names2:= '';
select product_id,name as category ,username as sellerUsername
from (
select a.product_id, c.name ,b.username,
#row_number:=CASE WHEN #db_names=username and #db_names2=name THEN #row_number+1
ELSE 1 END AS row_number,#db_names:=username AS username2,#db_names2:=name AS name2
from products as a
left join seller as b on b.seller_id = a.seller_id
left join category as c on c.category_id = a.category_id
where name IN ('electronics', 'clothing', 'furniture')
)a where row_number < 2
order by sellerUsername,name;
Output :

Mysql join 4 tables can it be done in one query

My database
category_group(id,name)
category(id,name,cat_group_id)
topic(id,name,cat_id)
comment(id,name,topic_id)
I want to get:
Category Group 1
=====================
Category 1
Count topic | Count comment
-------------------
Category 2
Count topic | Count comment
Category Group 2
=====================
Category 3
Count topic | Count comment
-------------------
Category 4
Count topic | Count comment
I can only do with a lot of different query but I think it is not good practice.
If all the table are strictly related you can use inner join
select a.*, b.*, c.*, d.*
from category as a
inner join category_group as b on a.cat_group_id = b id
inner join topic as c on a.id = c.cat_id
inner join comment as d.topic_id = c.id
else where need use left join
Then for in your case you can do this
select b.name, a.name, count(d.*) as count_commect, count(c.*) as count_topic
from category as a
inner join category_group as b on a.cat_group_id = b id
inner join topic as c on a.id = c.cat_id
inner join comment as d.topic_id = c.id
group by a.name, b.name
order by a.name, b.name

Write query without join and using subquery

I want to rewrite the join query with sub-query like IN(), ANY() operator.
Data set:
*categories*
categoryID name
5 ROD
7 CEMENT
*products*
productID categoryID name
7 5 BSRM 10mm
9 5 KSRM 5mm
10 5 Julius
11 7
12 5 BSRM 25mm
*sale_products*
saleID productID
118 9
119 9
120 9
121 9
122 12
123 12
124 12
This is my query to read saleID, product name and category name for which already have sold.
My query is:
SELECT sale_products.saleID, products.name, categories.name
FROM categories
INNER JOIN (products, sale_products)
ON categories.categoryID = products.categoryID
AND products.productID = sale_products.productID
Now I want to the result set without join and with the sub-query methodology.
I try in this way:
SELECT categories.name
FROM categories
WHERE categories.categoryID IN
(SELECT products.categoryID
FROM products
WHERE products.productID in
(SELECT sale_products.productID FROM sale_products))
this query only give me the category name but I need also saleID, product name.
Your original query looks queer. Why do you cross join products and sale_products?
It should better be:
select sp.saleid, p.name as product, c.name as category
from sale_products sp
join products p on p.productid = sp.productid
join categories c on c.categoryid = p.categoryid;
This is the straight-forward way to show the data. You can use subqueries instead, but I see no sense in it:
select
sp.saleid
(
select p.name
from products p
where p.productid = sp.productid
) as product,
(
select c.name
from categories c
where c.categoryid = p.categoryid
) as category
from sale_products sp;
Here is yet another query with subqueries. Again without any benefit over the simple query using direct joins on the tables.
select sp.saleid, p.name as product, c.name as category
from sale_products sp
join (select productid, name from products) p on p.productid = sp.productid
join (select categoryid, name from categories) c on c.categoryid = p.categoryid;

Mysql: How to get values from other table base from an id

Assuming that I have 3 tables on my database
Table:Category
category_id
Table:container
container_id
category_id
Table:products
container_id
product_id
How do you get all product_id based on a category_id?
For example I have these data inside my tables from above:
Table: category
sour
sweet
Bitter
Table: container
bottled
sachet
Table: product
sugar
vinegar
cocoa
How do you get all Product(tb_product) where category(tb_category) is sweet
You can use INNER JOIN to solve your problem.
SELECT a.*
FROM products a
INNER JOIN container b
on a.container_id = b.container_ID
INNER JOIN Category c
ON b.category_ID = c.categoryID
WHERE c.categoryName = 'sweete'
As you can see, I assume that the Category table has columns category_ID and categoryName. So in my example above,I've use category name to search for all products that belong on certain category.
select p.*
from Category c
join container c2 on c2.category_id = c.category_id
join product p on p.container_id = c2.container_id
where c.name = 'sweet';
Note the order of the tables in the query (which should perform faster than the other answer!)
you can use inner join like this:
SELECT a.product_id FROM products AS a INNER JOIN container AS b on a.container_id = b.container_Id INNER JOIN Category AS c on b.category_Id = c.category_id where c.category_id = 'new'

mysql count subtables and its subtables for its main table

Table 1 - Category
id | name
Table 2 - subcat
id | cid(category.id) | name
Table 3 - products
id | cid(category.id) | sid(subcat.id) | name
select a.* , count(b.id) as total
from category a left join
subcategory b on a.id=b.cid
group by a.id order by a.name
this gives the count of sub categories for each category
and I can run seperately for products so that i will get count of products for each category
what I want is the count of subcategories and the count of products for each category. How to form the query?
It should be like catename, count of (sub categories) and count of (products)
Because you may have sub-categories for a given category, but no products actually listed for such sub-category, you might not get the results you expect... This should catch both for you
select a.id,
a.name,
BySubCat.AvailableSubCategories,
ByProduct.ActualSubCats,
ByProduct.ProductCount
from
category a
left join
( select cid, count(*) as AvailableSubCategories
from subcat
group by cid ) BySubCat
on a.id = BySubCat.cid
left join
( select cid,
count( distinct sid ) as ActualSubCats,
count(*) ProductCount
from
products
group by
cid ) ByProduct
on a.id = ByProduct.cid
order by
a.name
Try this:
select c.name,count(sc.id),count(sub.pcount)
from subcat sc
inner join
(
select p.sid as subid, count(p.id) as pcount from Products p
inner join subcat sc on sc.id = p.sid
group by p.sid
) sub
on sub.subid = sc.id
inner join Category c on c.id = sc.cid
group by sc.id,sub.pcount