MySQL:select data in three table - mysql

I have three table in mysql:
1.t_item
itemID item_name
1 pen
2 luxury pen
2.s_item
itemID item_name
1 shoes
2 clothes
3 computer
3.track
trackID item_no item_type
1 1 t_item
2 2 t_item
3 2 s_item
And I want to get trackID, item name for item_no in table track.
How can I write the sql statement?In track,trackID 2,3 have same item_no but different item type, Can I use join?

Here you are:
(SELECT track.trackID, t_item.item_name FROM track
LEFT JOIN t_item ON track.item_no=t_item.itemID
WHERE track.item_type = 't_item')
UNION
(SELECT track.trackID, s_item.item_name FROM track
LEFT JOIN s_item ON track.item_no=s_item.itemID
WHERE track.item_type = 's_item')

Here you go, It will work:
(SELECT t.trackID,ti.item_name
FROM track t
LEFT JOIN t_item ti
ON t.item_no=ti.itemID AND t.item_type='t_item')
UNION
(SELECT t.trackID,si.item_name
FROM track t
LEFT JOIN s_item si
ON t.item_no=si.itemID AND t.item_type='s_item')

Yes, you can use JOIN like this:
SELECT t.trackID, t.item_no,
(CASE WHEN t.item_type = 't_item' THEN ti.item_name
WHEN t.item_type = 's_item' THEN si.item_name
END) AS item_name
FROM track t
LEFT JOIN t_item ti ON t.item_no = ti.itemID AND t.item_type = 't_item'
LEFT JOIN s_item si ON t.item_no = si.itemID AND t.item_type = 's_item';
Here is the sqlfiddle.

Related

Matching Exactly all values in IN clause

I am searching for the solution for this problem for hours now with no luck. I have a Workouts table as below. Each item in the workout table can have multiple target muscles, which are listed in the Target Muscles table.
Workouts table:
id
1
2
Target Muscles table:
id
muscle_key
workout_id
1
a
1
2
b
1
3
c
1
4
a
2
5
b
2
I need to fetch all items in the workouts table which match EXACTLY ALL target muscles keys in the given set, not less and not more. For example, given the set of muscle keys:
(a,b)
The desired output would be:
id
2
The row for workout id = 1 should NOT be selected since it contains an extra muscle key (c).
I am using the following query:
SELECT id
FROM workouts
LEFT JOIN target_muscles ON workouts.id = target_muscles.workout_id
WHERE target_muscles.muscle_key IN (a,b)
GROUP BY workouts.id
HAVING COUNT(DISTINCT target_muscles.muscle_key) = 2
The above query is also returning the workout id = 1, instead of only 2. How can I achieve this?
Any help is appreciated.
Skip the WHERE clause. Use HAVING to make sure exactly a and b are there.
SELECT workouts.id
FROM workouts
JOIN target_muscles ON workouts.id = target_muscles.workout_id
GROUP BY workouts.id
HAVING COUNT(DISTINCT target_muscles.muscle_key) =
COUNT(DISTINCT CASE WHEN target_muscles.muscle_key IN (a,b)
THEN target_muscles.muscle_key END)
AND COUNT(DISTINCT target_muscles.muscle_key) = 2
Can also be done as:
SELECT workouts.id
FROM workouts
JOIN target_muscles ON workouts.id = target_muscles.workout_id
GROUP BY workouts.id
HAVING MIN(target_muscles.muscle_key) = 'a'
AND MAX(target_muscles.muscle_key) = 'b'
AND COUNT(DISTINCT target_muscles.muscle_key) = 2
Or, perhaps less performant:
SELECT workouts.id
FROM workouts
JOIN (SELECT workout_id FROM target_muscles WHERE muscle_key = 'a'
INTERSECT
SELECT workout_id FROM target_muscles WHERE muscle_key = 'b'
EXCEPT
SELECT workout_id FROM target_muscles WHERE muscle_key NOT IN ('a', 'b')) dt
ON workouts.id = dt.workout_id
You can remove the filtering clause and use two conditions:
count of non-(a,b) muscle_keys = 0
distinct count of (a,b) muscle_keys = 2
SELECT w.id
FROM workouts w
LEFT JOIN target_muscles ts ON w.id = ts.workout_id
GROUP BY w.id
HAVING COUNT(CASE WHEN ts.muscle_key NOT IN ('a', 'b') THEN w.id END) = 0
AND COUNT(DISTINCT CASE WHEN ts.muscle_key IN ('a', 'b') THEN ts.muscle_key END) = 2
Check the demo here.
This is an other way to do it using inner join
select distinct s.id
from (
select w.id
from workouts w
inner join targets t on t.workout_id = w.id
group by workout_id
having count(1) = 2
) as s
inner join targets t on t.workout_id = s.id and t.muscle_key in ('a', 'b');
You can Try it from here : https://dbfiddle.uk/nPTQlhqT

MySql query on 3 different tables

I have 3 tables.
Owners:
ownerID name
1 josh
Pets:
petID name
1 M
2 x
3 f
4 h
PetsOwners:
petID ownerID
1 1
3 1
4 1
I have a query that returns the ownerID from a person. "SELECT ownerID FROM Owners WHERE name = 'josh';" This will return ownerID = 1. I need a query that returns all pets that josh owns. In this case will be "m", "f" and "h" according to the petsOwners table.
If you have ownerId use
SELECT p.name
FROM Pets p
JOIN PetsOwners po
ON p.petID = po.petID
WHERE po.ownerID = 1
If you only have the owner name, need join all 3 tables
SELECT p.name
FROM Pets p
JOIN PetsOwners po
ON p.petID = po.petID
JOIN Owners o
ON po.ownerID = o.ownerID
WHERE o.name = 'josh'
If you just want their names:
SELECT Pets.name
FROM Pets, PetsOwners, Owners
WHERE Pets.petID = PetsOwners.petID
AND Owners.ownerID = PetsOwners.ownerID;
try this:
select a.ownerID,a.`name`as OwnerName, b.petID,b.`name` as PetName from
(select ownerID `name` from Owners) as a
right join
(select a.petID,a.`name`,OwnerID from
(select petID,`name` from Pets) as a
left JOIN
(select petID,OwnerID from PetsOwners) as b
on a.petID = b.petID) as b
on a.ownerID = b.OwnerID
I see your question and this is easy you see the query I wrote blow:
SELECT links.`link`,
links.`link_id`
FROM links
WHERE links.`link_id` NOT IN
(SELECT Y.`link_id`
FROM users X
INNER JOIN user_visited Y ON X.`user_id` = Y.`user_id`
WHERE X.`user_id` = 22 );

MySQL Join 3 Tables with Count, Group & Where/Having Clause

I have 3 tables
TABLE ii_ProductCategory
-------------------
id title
TABLE ii_Product2Category
-------------------
categoryId productId
TABLE ii_Product
----------------
id minPrice
I want to find all Categories are either not contained in ii_Product2Category at all or are only linked to products that have minPrice IS NULL.
Here is my attempt. I am getting a GROUP BY ERROR.
SELECT COUNT(DISTINCT p2c.`categoryId`) as "ProdCount",
cat.`id`,
cat.`title`,
prod.`minPrice`
FROM `ii_ProductCategory` cat
LEFT JOIN `ii_Product2Category` p2c
ON p2c.`categoryId` = cat.`id`
LEFT JOIN `ii_Product` prod
ON p2c.`productId` = prod.`id`
WHERE prod.`minPrice` IS NULL
AND COUNT(DISTINCT p2c.`categoryId`) = 0
GROUP BY cat.`id`
I tried moving the prod.minPrice IS NULL to a HAVING on the join but that didn't work either. I also want to be able to drop the AND COUNT(DISTINCT p2c.categoryId) = 0 and sort by ProdCount so I can see total numbers of products in each whether they are null or not.
It doesn't make sense to not grouping the non-aggregated columns.
SELECT COUNT(DISTINCT p2c.`categoryId`) as "ProdCount",
cat.`id`,
cat.`title`,
prod.`minPrice`
FROM `ii_ProductCategory` cat
LEFT JOIN `ii_Product2Category` p2c
ON p2c.`categoryId` = cat.`id`
LEFT JOIN `ii_Product` prod
ON p2c.`productId` = prod.`id`
WHERE prod.`minPrice` IS NOT NULL
GROUP BY cat.`id`, cat.`title`, prod.`minPrice`
HAVING COUNT(DISTINCT p2c.`categoryId`) = 0

MYSQL - Union SELECT & GROUP BY Not working

I have 3 table, log, member, also guest, but my log i stored as customer(user)'s id only, which is either their guest_id or member_id. So here's the problem, because they're from different table, I'm not sure how to join & group together their data.
checkout_log table
id user_id checkout_as
--------------------------------------
1 1 member
2 2 guest
members table
id fullname
--------------------------------------
1 member01
2 member02
guests table
id fullname
--------------------------------------
1 guest01
2 guest02
What I wanted to Achieve - Result
id user_id fullname checkout_as
----------------------------------------------
1 1 member01 member
2 2 guest02 guest
Had tried following sql statement with UNION ALL, or GROUP BY , but had no luck.
SELECT * FROM
(
SELECT checkout_log.id,checkout_log.user_id,guests.fullname,guests.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN guests ON checkout_log.user_id = guests.id
UNION ALL
SELECT checkout_log.id,checkout_log.user_id,members.fullname,members.email,checkout_log.checkout_as
FROM checkout_log
LEFT JOIN checkout_product ON checkout_product.checkout_log_id = checkout_log.id
LEFT JOIN members ON checkout_log.user_id = members.id
) derivedTable
GROUP BY id
Try doing this with joins instead of union
select cl.id, cl.user_id,
coalesce(m.fullname, g.fullname) as fullname,
cl.checkout_as
from checkout_log cl left join
members m
on cl.user_id = m.id and cl.checkout_as = 'member' left join
guests g
on cl.user_id = g.id and cl.checkout_as = 'guest';

(My)SQL JOIN - get teams with exactly specified members

Assume tables
team: id, title
team_user: id_team, id_user
I'd like to select teams with just and only specified members. In this example I want team(s) where the only users are those with id 1 and 5, noone else. I came up with this SQL, but it seems to be a little overkill for such simple task.
SELECT team.*, COUNT(`team_user`.id_user) AS cnt
FROM `team`
JOIN `team_user` user0 ON `user0`.id_team = `team`.id AND `user0`.id_user = 1
JOIN `team_user` user1 ON `user1`.id_team = `team`.id AND `user1`.id_user = 5
JOIN `team_user` ON `team_user`.id_team = `team`.id
GROUP BY `team`.id
HAVING cnt = 2
EDIT: Thank you all for your help. If you want to actually try your ideas, you can use example database structure and data found here: http://down.lipe.cz/team_members.sql
How about
SELECT *
FROM team t
JOIN team_user tu ON (tu.id_team = t.id)
GROUP BY t.id
HAVING (SUM(tu.id_user IN (1,5)) = 2) AND (SUM(tu.id_user NOT IN (1,5)) = 0)
I'm assuming a unique index on team_user(id_team, id_user).
You can use
SELECT
DISTINCT id,
COUNT(tu.id_user) as cnt
FROM
team t
JOIN team_user tu ON ( tu.id_team = t.id )
GROUP BY
t.id
HAVING
count(tu.user_id) = count( CASE WHEN tu.user_id = 1 or tu.user_id = 5 THEN 1 ELSE 0 END )
AND cnt = 2
Not sure why you'd need the cnt = 2 condition, the query would get only those teams where all of users having the ID of either 1 or 5
Try This
SELECT team.*, COUNT(`team_user`.id_user) AS cnt FROM `team`
JOIN `team_user` ON `team_user`.id_team = `team`.id
where `team_user`.id_user IN (1,5)
GROUP BY `team`.id
HAVING cnt = 2