mysql group_concat with where in condition - mysql

I have three table product
ID name
1 A
2 B
3 C
vendor
ID Name
1 V1
2 V2
3 V3
product_vendor
ID pid vid
1 1 1
2 1 2
3 2 3
4 3 1
5 3 2
6 3 3
i want left join and create response like below table
p_id product vendors
1 A V1,V2
2 B V3
3 C V1,V2,V3
below is the my solution but it's quite complicated. Is it possible to have a short query for this
SELECT GROUP_CONCAT(v2.`name`) AS vendername,
p.*,
GROUP_CONCAT(v.`v_id`) AS vi
FROM `products` p
JOIN `product_vendor` v ON p.id = v.p_id,
`vendors` v2
WHERE v2.id IN
(SELECT GROUP_CONCAT(p.`id`) AS vi
FROM `vendors` p
JOIN `product_vendor` v ON p.id = v.p_id
GROUP BY p.id)
GROUP BY p.id
ORDER BY `p_id` ASC

Can you try this, I do not have executed the query but thinks it will help:
SELECT `P`.`id`, `P`.`name`, CONCAT(GROUP_CONCAT(CAST(`V`.`name` AS CHAR)), ", ") as vendername
FROM `product` P
JOIN `product_vendor` PV ON (`PV`.`pid` = `P`.`id`)
JOIN `vendor` V ON (`V`.`ID` = `PV`.`vid`)
GROUP BY `PV`.`pid`
For listing all records in Product table use:
SELECT `P`.`id`, `P`.`name`, CONCAT(GROUP_CONCAT(CAST(`V`.`name` AS CHAR)), ", ") as vendername
FROM `product` P
LEFT JOIN `product_vendor` PV ON (`PV`.`pid` = `P`.`id`)
LEFT JOIN `vendor` V ON (`V`.`ID` = `PV`.`vid`)
GROUP BY `PV`.`pid`
ORDER BY `P`.`id`

Just do it with joins and group_concat no need for sub queries
SELECT
p.id,
p.name,
Group_concat(v.name) AS vendername
FROM
product p
JOIN
product_vendor pv ON p.id = pv.pid
JOIN
vendor v ON pv.vid = v.id
GROUP BY
p.id, p.name
ORDER BY
p.id ASC
Demo

Related

Mysql query count total from other table

Table jenis_usaha
ID JENIS_USAHA
1 Laundry
2 Restauran
Table waralaba
ID ID_JENIS_USAHA
1 1
2 2
Table perusahaan
ID NAME ID_WARALABA
1 A 1
2 B 2
3 C 1
4 D 1
Table outlet
ID ID_PERUSAHAAN
1 1
2 1
3 2
4 2
5 1
6 1
7 1
8 1
9 1
The result that I want is like this
ID JENIS_USAHA TOTAL_PERUSAHAAN TOTAL_OUTLET
1 Laundry 3 7
2 Restauran 1 2
I have this mysql query
SELECT ju.ID,
ju.JENIS_USAHA,
COUNT(p.ID) AS TOTAL_PEMBERI,
(SELECT count(o.ID)
FROM outlet o
WHERE p.ID = o.ID_PERUSAHAAN
AND w.ID = p.ID_WARALABA
AND ju.ID = w.ID_JENIS_USAHA
) AS TOTAL_OUTLET
FROM jenis_usaha ju
LEFT JOIN waralaba w ON w.ID_JENIS_USAHA = ju.ID
LEFT JOIN perusahaan p ON p.ID_WARALABA = w.ID
GROUP BY ju.ID
I've got no error BUT a wrong result for TOTAL_OUTLET. Could you please show me the right query for this? thanks
you did the wrong join that's why you got wrong output
below query should work as your way
select j.id ,j.name,TOTAL_PERUSAHAAN,outlet as TOTAL_OUTLET
from jenis_usaha j inner join
(select p.id,count(o.ID_PERUSAHAAN) as outlet from outlet o
inner join perusahaan p
on o.ID_PERUSAHAAN=p.id
group by p.id
) t1
on t1.id=j.id
inner join
(
select w.id, count(p.ID_WARALABA) as TOTAL_PERUSAHAAN
from waralaba w inner join perusahaan p
on w.id=p.ID_WARALABA
group by w.id
) t2
on t2.id=j.id
id name TOTAL_PERUSAHAAN TOTAL_OUTLET
1 Laundry 3 7
2 Restauran 1 2
here is fiddle link where you can find details
http://sqlfiddle.com/#!9/400c971/6
I was taking very long to understand your query, so I decided to do my own.
This one bring the results you wanted anyway. Please check if this works for your case. =)
Btw, st stands for subtotal
SELECT
st.id,
st.name,
count(ps_id) AS ps_amount,
sum(ol_amount) AS ol_amount
FROM
(SELECT
ju.id,
ju.name,
ps.id AS ps_id,
count(ol.id) as ol_amount
FROM
jenis_usaha ju
INNER JOIN
waralaba wl
ON wl.id_jenis_usaha = ju.id
LEFT JOIN
perusahaan ps
ON ps.id_waralaba = wl.id
LEFT JOIN
outlet AS ol
ON ol.id_perusahaan = ps.id
GROUP BY
ju.id,
ju.name,
ps.id) st
GROUP BY
st.id,
st.name

Get categories which do not have any product from a particular category

I am trying to write a sql query to get the categories which does not have any of the products from particular category. Let say I have a,b,c,d,e categories and each category have some products. Now I need to get all the categories which done not include products of category a.
Categories table:
id name
1 A
2 B
3 C
4 D
5 E
category_products table:
product_id category_id
1 1
1 2
2 3
2 1
4 3
3 2
3 4
3 5
4 5
Query I used is below which gives B,C,D,E (not as expected)
SELECT DISTINCT c.name FROM category_products AS p
LEFT JOIN categories AS c ON c.id = p.category_id
WHERE p.product_id NOT IN (SELECT DISTINCT product_id FROM category_products where category_id = 1)
ORDER BY c.name
But I need results to be categories D,E which don't have any products from category A.
You need to do one more inner query, e.g.:
SELECT name
FROM categories
where id NOT IN (
SELECT DISTINCT category_id
FROM category_products WHERE
product_id IN (
SELECT product_id FROM category_products WHERE category_id = 1
)
);
This would return D and E.
Here's the SQL Fiddle.
You should use inner join
select distinct t2.name
from category_products t1
inner join Categories t2 on t2.id = t1.category_id
where t1.product_id not in
(select p.product_id
from category_products p
inner join Categories c on c.id = p.category_id
where c.name ='A')
I would be inclined to do this using group by and having:
select pc.product_id
from category_products pc join
categories c
on c.id = pc.category_id
group by pc.product_id
having sum(c.name = 'A') = 0;

Count two different rows in mysql query

I have organizations. Each organization can have members and projects.
I want to get list of organizations with number of members and projects.
For example,
Organization | Members | Projects | Action
------------------------------------------
Org 1 | 5 | 6 | Delete - Edit
Org 2 | 2 | 9 | Delete - Edit
I am using this query,
SELECT COUNT(m.id) as members, COUNT(p.id) as projects,
o.status,o.organization_name,o.logo, o.id as id
from tbl_organizations o
LEFT JOIN tbl_organization_members m ON (o.id = m.organization_id)
LEFT JOIN tbl_projects p ON (o.id = p.organization_id)
WHERE o.status= 'active' AND o.created_by= 1
But the output of number of projects is equal to number of members.
How can I make the sample above using query?
Try this way:
SELECT o.id as id, o.organization_name, cnt_ as members, cnt_p as projects
from tbl_organizations o
LEFT JOIN (
SELECT organization_id, COUNT(id) cnt_m
FROM tbl_organization_members
GROUP BY organization_id
) m ON (o.id = m.organization_id)
LEFT JOIN (
SELECT organization_id, COUNT(id) cnt_p
FROM tbl_projects
GROUP BY organization_id
) p ON (o.id = p.organization_id)
WHERE o.status= 'active' AND o.created_by= 1
This way you JOIN to an already aggregated version of member/project tables, so as to get the count of members/projects per organization_id.
Group by the organisation columns and count distinct IDs
SELECT o.status,o.organization_name, o.logo, o.id as id,
COUNT(distinct m.id) as members, COUNT(distinct p.id) as projects,
from tbl_organizations o
LEFT JOIN tbl_organization_members m ON (o.id = m.organization_id)
LEFT JOIN tbl_projects p ON (o.id = p.organization_id)
WHERE o.status= 'active'
AND o.created_by= 1
GROUP BY o.status, o.organization_name, o.logo, o.id
You can co-related subquery:
SELECT
o.id as Organization,
(SELECT COUNT(*) FROM tbl_organization_members WHERE organization_id = o.id) as members,
(SELECT COUNT(*) FROM tbl_projects WHERE organization_id = o.id) as projects
FROM
tbl_organizations o
WHERE
o.status= 'active' AND o.created_by = 1

Finding similar records based on a connector table with many-to-many relations

I have 3 tables Products,ProductHas,Props. Needless to say each product has more than one prop which is kept in the ProductHas table. I'm trying to find the Product B which is closest to Product A interms of similarities of their props.
Current structure of the tables look like this.
+----------+----------+-----------+
|Products |ProductHas|Props |
+----------+----------+-----------+
|product_id|product_id|prop_id |
+----------+----------+-----------+
| name | prop_id |description|
+----------+----------+-----------+
Another option
SELECT A.Name, B.Name, COUNT(*)
FROM (
SELECT p.name, pp.description
FROM Products p
INNER JOIN ProductHas ph ON ph.product_id = p.product_id
INNER JOIN Props pp ON pp.prop_id = ph.prop_id
) AS A INNER JOIN (
SELECT p.name, pp.description
FROM Products p
INNER JOIN ProductHas ph ON ph.product_id = p.product_id
INNER JOIN Props pp ON pp.prop_id = ph.prop_id
) AS B ON B.description = A.Description
WHERE A.Name = 'A'
GROUP BY
A.name, B.Name
ORDER BY
COUNT(*) DESC
Try:
select h1.product_id, count(h0.prop_id) count_matches, count(*) total_props
from ProductHas h1
left join ProductHas h0
on h0.product_id = ? and h0.prop_id = h1.prop_id and h0.product_id <> h1.product_id
group by h1.product_id
order by 2 desc
limit 1
you could try a fulltext index on the props table, i
CREATE TABLE Props(
prop_id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
description TEXT,
FULLTEXT (description)
) ENGINE=MyISAM;
(I don't know anything about the size of the description but if you know its limit then you should put it like description VARCHAR(200))
SELECT *
FROM Props prod_a_props,
Props prod_b_props,
ProductHas prod_a_rel
WHERE prod_a_rel.product_id = :your_product_A_id
AND prod_a_props.prop_id = prod_a_rel.prop_id
AND MATCH (prod_b_props.description) AGAINST (prod_a_props.description);
Try something like this:
SELECT B.product_id
FROM Products B
INNER JOIN
ProductHas HB
INNER JOIN
ProductHas HA
INNER JOIN
Products A
ON HA.product_id = A.product_id
ON HA.prop_id = HB.prop_id
AND HA.product_id != HB.product_id
ON B.product_id = HB.product_id
WHERE A.product_id = xxx
GROUP BY B.product_id
ORDER BY COUNT(A.product_id) DESC
LIMIT 1

MySQL join issue

I am trying to return the results of the products in the product table that were not added by the current user and that the current user has not already reviewed, then sort by the products that have had the least reviews showing those with none first.
tblUsers:
UserID
1
2
3
tblProducts:
ProductID UserID (created) NumberReviews
--------- ---------------- -------------
1 1 1
2 1 0
3 2 1
4 1 2
5 2 0
tblReviews:
ReviewID UserID(reviewed) ProductID
-------- ---------------- ---------
1 2 4
2 1 3
3 3 4
4 3 1
So for a current user of 2 I want to return
Product ID
----------
2
1
I have tried a number of different left joins but to no avail. Any ideas?
SELECT p.*
, COUNT(r.ProductID) AS reviews
FROM tblProducts AS p
LEFT JOIN tblReviews AS r
ON r.ProductID = p.ProductID
WHERE UserID <> #currentUser
AND NOT EXISTS
( SELECT *
FROM tblReviews ru
WHERE ru.ProductID = p.ProductID
AND ru.UserID = #currentUser
)
GROUP BY p.ProductID
ORDER BY reviews ASC
If you don't want to count but use the field NumberReviews for ordering, it's simpler:
SELECT p.*
FROM tblProducts AS p
WHERE UserID <> #currentUser
AND NOT EXISTS
( SELECT *
FROM tblReviews ru
WHERE ru.ProductID = p.ProductID
AND ru.UserID = #currentUser
)
ORDER BY NumberReviews ASC
Try with:
SELECT u.*, p.*, r.* FROM users u
LEFT JOIN products p ON p.userId <> u.userID
LEFT JOIN reviews r ON ( r.productId = p.ProductID AND r.UserID = u.userID)
GROUP BY p.productID ORDER BY p.NumberReviews
Something along these lines might work (sql server syntax, not sure about mysql)
Select productID
from Users u
-- all products not created by user
inner join Products p on p.UserID != u.UserID
-- that were reviewed by the user. NOT!
left outer join Reviews r on p.ProductID = r.ProductID and r.UserID = u.UserID
where r.ReviewID is null
and User = CurrentUser
If I didn't miss anything:
SELECT
p.ProductID
FROM tblProducts p
LEFT JOIN tblReviews r ON p.ProductID = r.ProductID AND r.UserID = #UserID
WHERE p.UserID <> #UserID
AND r.ReviewID IS NULL
ORDER BY p.NumberReviews