MySQL query from data normalized tables - mysql

I have three tables:
users
user_id username
---------------------
1 | mrzander
2 | foo
3 | bar
---------------------
interests
interest_id interest
------------------------
1 | cars
2 | power tools
3 | shaving
4 | phones
5 | computers
------------------------
user_interests
id uid iid
-----------------
1 | 1 | 2
2 | 1 | 4
3 | 2 | 3
4 | 1 | 5
-----------------
Basically, I have a table of users, a table of interests, and a table that shows what users have what interests. If I know what user id I want the interests from, what query would give me all of a particular users interests?
In this example, what query would return a table called "Interests" that tells me user_id = 1 likes power tools, phones, and computers?

If you want the result on same row you should use join and group concat
select c.username, group_concat( b.interst)
from user_interest as a
left join interest as b on a.iid = b.interest_id
left join users as c. on c.user_id = a.uid
where c.user_id = 1
group by c.username
or if you need result on different rows se join only
select c.username, b.interst
from user_interest as a
left join interest as b on a.iid = b.interest_id
left join users as c. on c.user_id = a.uid
where c.user_id = 1

Simply join the two tables.
select i.*
from interests i
join user_interests u
on u.iid = i.interest_id
where i.uid = 1;

Related

Mysql : Join 4 table problem with the result

I have 4 table and join with all then i want show data like here :
pr_id |nama | jumlah_liker | id_user
1 |Milk | 5 | 1
2 |Choco| 0 | 1
Review Table produk
pr_id | nama
1 | Milk
2 | Choco
3 | Salad
Review Table liker
id_produk | id_user
1 | 1
1 | 1
1 | 1
1 | 3
1 | 2
Review Table featured_ukm
id | id_produk
1 | 1
2 | 2
But i got sql record
id_produk | nama | jumlah_liker | id_user
1 | milk | 1 | 1 //problem row i dont get count all record id_produk
2 | choco | 0 | 1
SELECT produk.*, COUNT(liker.id_produk), liker.id_user
FROM produk
left join liker ON liker.id_produk = produk.pr_id AND liker.id_user = 1
INNER JOIN featured_ukm ON featured_ukm.id_produk = produk.pr_id
GROUP BY featured_ukm.id_produk
Edit: My suggestions are first, I actually put what will produce your exact requested results at the bottom
It appears that you're trying to show how many likes each of the "Featured Product" has.
It isn't entirely clear what you're trying to do with the user id, or what its purpose in the result set is; here is a query to show how many likes each "Featured Product" has:
SELECT
produk.*,
(SELECT IFNULL(COUNT(*), 0)
FROM liker WHERE liker.id_produk = produk.pr_id)
FROM featured_ukm F
INNER JOIN produk ON produk.pr_id = F.id_produk
Here is a query to show how many likes each product by each user
SELECT DISTINCT
P.*,
(SELECT IFNULL(COUNT(*), 0) FROM liker WHERE liker.id_user = L.id_user),
IFNULL(L.id_user, 0)
FROM produk P
LEFT JOIN liker L ON L.id_produk = P.pr_id
and if you want to just see the items that ONE user liked, add:
WHERE L.id_user = 1
to the end of it.
Here is a query to show how many likes each Featured Product has for each user id:
SELECT DISTINCT
P.*,
(SELECT IFNULL(COUNT(*), 0) FROM liker WHERE liker.id_user = L.id_user),
IFNULL(L.id_user, 0)
FROM produk P
LEFT JOIN liker L ON L.id_produk = P.pr_id
INNER JOIN featured_ukm F on F.id_produk = P.pr_id
To get the exact result set that it would appear that you're looking for (in your example), you will need to reference a user table in your query. I assume you have one because you're referencing user ids. For the purpose of this example, I'm creating the below user table.
id | name
----------------
1 | user_one
2 | user_two
3 | user_three
With this table, the following query will give exactly what it appears you're looking for:
SELECT P.*, (SELECT IFNULL(COUNT(*), 0) FROM liker WHERE liker.id_produk =
F.id_produk), user.id
FROM user
CROSS JOIN featured_ukm F
LEFT JOIN produk P ON F.id_produk = P.pr_id
WHERE user.id = 1
But play around with some of my other example queries. They may be more helpful.

MYSQL - Group Contact rows with records NOT IN

My case looks simple but i'm messing around with this..
I have 4 tables: User, Macros, Categories, and another one that relate users with categories. One Macro have many Categories.
What i need, is a query that based on the Macro, get the users and the Categories where user is NOT IN.
Example: I have a macro named VEICULES, with categories CAR,TRUCK and Motorcycle. User José is on category CAR and User Julio on category CAR and TRUCK, so my query should return:
José | TRUCK,Motorcycle
Julio | Motorcycle
Tables:
prd_users
id | name | Email
---------------------------
1 | José | jose#email.com
2 | Júlio | julio#email.com
3 | André | andre#email.com
cat_macros
macro_id | macro_name
-----------------------
1 | Veicules |
cat_categories
category_id | category_name | macro_id
---------------------------------------
1 | Cars | 1
2 | Trucks | 1
3 | Motorcycles | 1
prd_tr_rabbit_catg
id | category_id | tasker_user_id
---------------------------------------
1 | 1 | 1
2 | 1 | 2
3 | 2 | 2
I'm stucked on just getting the categories where the user already is ..
SELECT prd_users.id, prd_users.name,
prd_users.email,cat_macros.macro_name as macro,
GROUP_CONCAT(cat_categories.category_name SEPARATOR ', ') as in_categories
FROM prd_users
INNER JOIN prd_tr_rabbit_catg ON prd_tr_rabbit_catg.tasker_user_id = prd_users.id
INNER JOIN cat_categories ON cat_categories.category_id = prd_tr_rabbit_catg.category_id
INNER JOIN cat_macros ON cat_macros.macro_id = cat_categories.macro_id
WHERE cat_macros.macro_id = '45'
GROUP BY prd_users.id;
To solve this problem it's necessary to create a list of all users joined with all categories for the given macro category. This can be done with a CROSS JOIN:
SELECT *
FROM prd_users u
CROSS JOIN (SELECT m.macro_id, m.macro_name, c.category_name, c.category_id
FROM cat_macros m
JOIN cat_categories c ON c.macro_id = m.macro_id) c
This can then be LEFT JOINed to the prd_tr_rabbit_catg table and by selecting those rows where there is no matching entry in the prd_tr_rabbit_catg table, we can find the users who don't have an entry for the given category:
SELECT c.macro_name, u.id AS user_id, u.name, u.Email, GROUP_CONCAT(c.category_name) AS missing_cats
FROM prd_users u
CROSS JOIN (SELECT m.macro_id, m.macro_name, c.category_name, c.category_id
FROM cat_macros m
JOIN cat_categories c ON c.macro_id = m.macro_id) c
LEFT JOIN prd_tr_rabbit_catg x ON x.tasker_user_id = u.id AND x.category_id = c.category_id
WHERE x.id IS NULL
AND c.macro_id = 1
GROUP BY c.macro_name, u.id
For your sample data, this gives:
macro_name user_id name Email missing_cats
Veicules 1 José jose#email.com Motorcycles,Trucks
Veicules 2 Júlio julio#email.com Motorcycles
Veicules 3 André andre#email.com Cars,Motorcycles,Trucks
Update
To exclude users who don't have any of the categories, add a HAVING clause:
HAVING COUNT(*) < (SELECT COUNT(*) FROM cat_categories WHERE macro_id = 1)
Demo on SQLFiddle

Mysql select query - stuck in where condition

I have 2 tables:
Users:
------------------------------
id | name
--------------------------
1 | John
2 | Dane
3 | Foo
4 | Bar
Matches Table:
----------------------------
id | userid1 | userid2
----------------------------
1 | 1 | 3
2 | 2 | 4
Question:
From the matches table with id 1, i want to fetch John and Foo in one query. How can i do that ?
I already have one solution but its dull. That is selecting records from matchs tables and then while looping, trigger queries for getting names. .
Just use a JOIN...
SELECT u1.*, u2.*
FROM Matches m
JOIN Users u1 ON u1.id = m.userid1
JOIN Users u2 ON u2.id = m.userid2
WHERE m.id = [ YOUR DESIRED USER ID (for example: 1) ]
SELECT name from Matches, Users where Matches.id = 1 AND (Users.id = Matches.userid1 OR Users.id = Matches.userid2)
This should work.

Creating multiple joins accessing the same table

I need a way to extract two user names from the same table. I'm able to pull the first name (jim), but I'm having trouble pulling from the second criteria/join.
The two tables:
tbl_users
usr_index | usr_name
1 | bob
2 | mike
3 | jim
tbl_master
mas_openedby | mas_closedby
3 | 1
1 | 3
2 | 2
tbl_master.mas_openedby = 3
tbl_master.mas_closedby = 2
first results should be(opened by): jim
sec. results should be(closed by): mike
select tbl.users.usr_name
...
FROM tbl_master
LEFT JOIN tbl_users ON tbl_users.usr_index = tbl_master.mas_openedby
LEFT JOIN tbl_users ON tbl_users.usr_index = tbl_master.mas_closedby
You need to assign each join a unique alias:
LEFT JOIN tbl_users AS userjoin1 ON userjoin1.usr_index = tbl_master.mas_openedby
LEFT JOIN tbl_users AS userjoin2 ON userjoin2.usr_index = tbl_master.mas_closedby
... then:
SELECT userjoin1.usr_name, userjoin2.usr_name FROM...

How to do this JOIN to SELECT from 2 MySQL tables?

I'm very new to joins, so far I've been doing relatively simple joins but this one got me stumped.
I have 2 tables that look like this:
Friends Table
friendship_id | friend_init | friend_accept | status
1 | 18 | 10 | 1
2 | 13 | 18 | 0
Users Table
user_id | email | username | password | kittens, etc...
10 | -- | -- | -- | --
13 | -- | -- | -- | --
18 | -- | -- | -- | --
If I am trying to select all the info about user_id 18's friends from both tables where the friends record status = 1, what would the join look like?
SELECT users.*
FROM users JOIN friends ON friends.friend_accept = users.user_id
WHERE friend.friend_init = 18 AND friend.status = 1
UNION
SELECT users.*
FROM users JOIN friends ON friends.friend_init = users.user_id
WHERE friend.friend_accept = 18 AND friend.status = 1
Drop the UNION... if your database is symmetrical (you have both (18,10) and 10,18), or if you only want to see friendships from one side.
Select *
from users
LEFT join Friends
ON Users.User_ID = Friends.Friend_init
OR users.User_ID = Friends.Friend_Accept
Where Friends.Status = 1
LEFT join is used because if a user has no FRIENDS yet; the user will still show up.
select *
from user u
join friends f
on u.user_id = f.friends_accept
where u.user_id = 18 and f.status = 1
union
select *
from friend f
join user u
on u.user_id = f.friend_status
where u.user_id = 18 and f.status = 1