MySQL join issue - mysql

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

Related

Select count of total products as well as out of stock products from table

I have to 3 tables: product, product_to_store, store
product table
id quantity status
1 1 1
2 0 1
3 0 1
4 23 1
product_to_store table
store_id product_id
1 1
2 2
1 3
2 4
store table
id name
1 store1
2 store2
To find total products I can run query to fetch all products in table product where status of product is enabled.
select count(*) from product where status=1
total name
2 Store 1
2 store 2
To find total out of stock products I can run below query after joining all 3 tables and using group by store_id:
Select count(*) as outofproducts from product where quantity=0;
Result come like this:
outofproducts name
1 Store 1
1 store 2
But I want combination of above 2 results in single query like below:
outofproducts total name
1 2 Store 1
1 2 store 2
You'd use conditional aggregatiopn, i.e. sum/count over conditions:
select
s.name,
sum(p.quantity > 0) as in_stock,
sum(p.quantity = 0) as out_of_stock,
count(*) as total
from store s
join product_to_store ps on ps.store_id = s.id
join product p on p.id = ps.product_id
group by s.name
order by s.name;
This makes use of MySQL's true = 1, false = 0. If you don't like it, replace sum(p.quantity = 0) with sum(case when p.quantity = 0 then 1 else 0 end) or count(case when p.quantity = 0 then 1 end).
You can start query from store table so that we will get total rows as store table data.
Then use nested query for each store to get out of product and total product count
select
(Select count(*) as outofproducts from product_to_store ps inner join product p on p.id = ps.product_id where quantity=0 and ps.store_id = s.id ) as outofproducts ,
(Select count(*) as count from product_to_store ps inner join product p on p.id = ps.product_id where ps.store_id = s.id ) as totalCount,
s.name
from store s
You could join the related subquery for count
select t1.name, t1.outofproducts, t2.total
from(
select b.id, b.name , count(*) outofproducts
from product_to_store c
inner join product a on a.id = c.product_id
inner join store b on a.id = c.store_id
where a.quantity = 0
group by b.id, b.name
) t1
inner join (
select b.id, b.name , count(*) total
from product_to_store c
inner join product a on a.id = c.product_id
inner join store b on a.id = c.store_id
group by b.id, b.name
) t2 on t1.id = t2.id

mysql group_concat with where in condition

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

sum() returns incorrect value with join

Here i have tables
1) users_interests
user_id interest_id
677 12
677 14
677 13
2) answer_points
user_id in_id point
677 12 -1
677 12 1
677 12 1
677 14 1
678 14 1
3) interests
id name
12 movie
13 cooking
14 music
here what i want to do is,I want output like this
interest_id name point
12 movie 1
13 cooking 0
14 music 1
Where user_id=677
I tried this query
select ui.interest_id,i.name,sum(a.answer_points) as total from
users_interests as ui inner join interests as i on i.id=ui.interest_id
left join answer_points as a on a.in_id=ui.interest_id
where i.user_id='677' group by a.in_id
But its not counting 1 vote. it returns 3 total for movie
This code will work for your requirement, Also check this below link
http://rextester.com/NQXE66482
SELECT
J.interest_id AS 'ID',
I.NAME AS 'NAME',
CASE WHEN K.TOTAL != 0 THEN K.TOTAL
ELSE 0 END AS 'Total'
FROM
users_interests AS J
JOIN
interests AS I
ON
J.interest_id = I.id
LEFT JOIN
(SELECT
a.id AS 'ID',
a.name AS 'NAME',
SUM(b.point) as 'TOTAL'
FROM
interests a
LEFT JOIN
answer_points b
ON a.id = b.in_id
WHERE user_id = 677
GROUP BY 1) AS K
ON
J.interest_id = K.id
WHERE
J.user_id = 677
GROUP BY 1
ORDER BY 1
try this
select id,name,coalesce(find_in_set(id,in_id),0) as points
from interests i
left join(select distinct in_id
from answer_points a where point = 1)a
on a.in_id = i.id cross join users_interest u
where u.user_id = 677 group by id;
I just had to change JOIN little like this,
select ui.interest_id, i.name, COALESCE(SUM(a.answer_points),0) as total from users_interests as ui
join interests as i on i.id = ui.interest_id
left join answer_points as a on a.in_id = ui.interest_id AND a.user_id = ui.user_id
where ui.user_id='677'
group by a.in_id
I had to compare user_id as well in join like this AND a.user_id = ui.user_id
You should use left join starting for interests
select i.id, sum(a.point)
from interests as i
left users_interests as ui on ui.interest_id = i.id
left join answer_points as a on a.user_id = ui.user_id and a.in_id = i.interest_id
where i.user_id=677
group by a.id

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

SQL INNER JOIN and COUNT

I have 3 tables (user, item, userlike) and 2 sql queries. How can I unify these two queries?
SELECT item.userid, item.id, user.name FROM item
INNER JOIN user ON item.userid = user.id
SELECT userid,itemid, COUNT(*) AS `liked` FROM userlike
WHERE userid=9
GROUP BY itemid
I want to know whether a specific user (9) has liked the item or not.
Result should be somthing like this
itemid userid name liked* (*whether 'user 9' liked this item or not)
1 7 foo 0
2 4 asd 1
Thanks
You want to use an OUTER JOIN for this
SELECT i.id itemid, u.id userid, u.name, COALESCE(liked, 0) liked
FROM item i JOIN user u
ON i.userid = u.id LEFT JOIN
(
SELECT itemid, COUNT(*) liked
FROM userlike
WHERE userid = 9
GROUP BY itemid
) l
ON i.id = l.itemid;
or
SELECT i.id itemid, u.id userid, u.name, l.userid IS NOT NULL liked
FROM item i JOIN user u
ON i.userid = u.id LEFT JOIN userlike l
ON i.id = l.itemid
AND l.userid = 9;
Sample output:
| ITEMID | USERID | NAME | LIKED |
|--------|--------|-------|-------|
| 2 | 4 | user4 | 1 |
| 1 | 7 | user7 | 0 |
Here is SQLFiddle demo
SELECT item.id, item.userid, user.name, userlike.liked
FROM item
JOIN user ON user.id = item.userid
JOIN userlike ON item.id = userlike.itemid
WHERE userlike.liked = 1
GROUP BY item.id
OR
SELECT item.id, item.userid, user.name, userlike.liked
FROM item
JOIN user ON user.id = item.userid
JOIN userlike ON item.id = userlike.itemid
WHERE COUNT(userlike.liked) >= 1
GROUP BY item.id
You don't need to use COUNT. You just need to know if there is an entry for a specific item and a specific user in the userlike table :
SELECT i.id as itemid, u.id as userid, u.name,
case when ul.userid is null then 0 else 1 end as liked
FROM item i
INNER JOIN user u ON i.userid = u.id
LEFT OUTER JOIN userlike ul ON i.id = ul.itemid AND ul.userid=9
ORDER BY i.id