Three way join with linking table - mysql

This is what I'd think is a fairly common pattern, but I'm just struggling with the appropiate query for it.
User Table
id
Member table
id
name
User Member link table
user_id
member_id
A user may exist in the user's table, but not have a row in the User Member link table.
I want to select all rows of the User table, and where a user has a link to a member in the user member link table to show the columns linked to them from the member table.
Here's what I've got, but it only gets the rows from the User table that are linked:
SELECT user.id, user.username, member.id, member.name
FROM users
LEFT JOIN user_member ON user.id = user_member.user_id
JOIN member ON user_member.member_id = member.id;
I should get something like this:
user.id user.username member.id member.name
1 bob null null
2 alice 10 Alice
3 jane 11 Jane
4 joe null null
Any suggestions?

I assume a member_id in the user_member table always has a corresponding row in the member table. First, join member and user_member. Second, join user.
SELECT user.id, user.username, member.id, member.name
FROM users
LEFT JOIN
(user_member INNER JOIN member ON user_member.member_id = member.id)
ON user.id = user_member.user_id;

Try using a CROSS JOIN
SELECT user.id, user.username, member.id, member.name
FROM users u
CROSS JOIN member m
LEFT JOIN user_member um
ON u.id= um.user_id
AND m.id= um.member_id

Related

SQL INNER JOIN only returns the first result

I have a Many to Many relationship between Pets and Users, with a UserPets join table. I've been trying to write an SQL query that would return the user name with the amount of times walked. However, I've only been able to return a user and a timesWalked and they are not even the associated ones.
The current SQL statement I have is:
SELECT user_pets.timesWalked, users.name
FROM user_pets
INNER JOIN users ON user_pets.user_id = users.id
And the returned result is:
[{"timesWalked"=>20, "name"=>"user1", 0=>20, 1=>"user1"}]
In this instance, user1 is not the one that walked the dog 20 times, which is the association I need.
table name: users
name
user1
user2
user3
table name: user_pets
name timesWalked userId petId
usep1 10 2 1
usep2 20 1 3
usep3 5 1 2
table name: pets
name
pet1
pet2
pet3
My expected result is:
[{"timesWalked"=>20, "name"=>"user1"}]
[{"timesWalked"=>10, "name"=>"user3"}]
[{"timesWalked"=>5, "name"=>"user2"}]
In this instance, the user name from the User's table is being associated with timesWalked from the user_pets table
How can I return all the timesWalked with all the user names who walked the pet?
You can use inner join to achieve this.
Below query lists all the users who have walked all the pets for total number of time.
i.e. User 1 has walked two pets for 2 times each.
select
up.timesWalked, u.name as UserName, p.name as PetName
from user_pets up
inner join users u on up.user_id = u.id
inner join pets p on up.pet_id = p.id
Have a look at this fiddle : http://sqlfiddle.com/#!17/c91a1/2

Using multiple columns in a join on same field in second table

Consider the following :
**Table 1 - record**
id (int primary key),
addedby (int),
editedby (int)
**Table 2 - users**
id (int primary),
name (shorttext)
**Sample Records**
record
0 1 1
1 1 2
users
1 user1
2 user2
What I need is so do a join to to be able to show the following :
record.id, users.addedby, users.editedby
I tried, amongst others, the following :
select record.id, users.name, users.name from record left join users on record.addedby=users.id left join users on record.editedby=users.id
However, it's not even logical that that will work, so I am a bit stuck.
Any help would be much appreciated. Thank you.
Just join the same table twice. Nothing unusual. You just have to alias the tables to be able to refer to them independently.
select r.id, u1.name added, u2.name editor
from record r
inner join user u1
on r.addedby = u1.id
inner join user u2
on r.editedby = u2.id
heres a demo
Use aliasses:
select record.id, users1.name, users2.name
from record
left join users users1 on record.addedby=users1.id
left join users users2 on record.editedby=users2.id

Mysql, double join that use the same table twice, but indirectly

There are plenty of question about join on the same table, but I can't find something related to my problem
I have two tables:
user (id, name)
friends (from, to)
And I have the following query. It is supposed to retrieve all users with their friends :
SELECT user.id, user.name, f.to, friend.id, friend.name
FROM user
LEFT JOIN friends f ON user.id = f.from
LEFT JOIN user friend ON user.id = f.to
LIMIT 0, 200
It returns something like this:
id name from to id name
1 bob 1 3 NULL NULL
1 bob 1 4 NULL NULL
2 toto 2 7 NULL NULL
The from and two are correct, but the second join doesn't seem to work. Do you have any ideas what is wrong with the second join ?
Try this:
SELECT user.id, user.name, f.to, friend.id, friend.name
FROM user
LEFT JOIN friends f ON user.id = f.from
LEFT JOIN user friend ON friend.id = f.to
LIMIT 0, 200
Note that I replaced user with friend in the join condition.

Show number of users in groups, even empty groups

I am trying to pull out the information about each user group, while counting the number of users in each.
The counting works, however if a group does not contain any users, it does not retrieve the information - it simply gets ignored.
This is my query:
SELECT
g.*,
count(u.username) as total,
u.usergroup
FROM
usergroups as g,
users as u
WHERE
u.usergroup = g.g_id
GROUP BY
g.group_name
This is a part of my "users" and "user groups" tables:
Sample usergroups table structure
+--------------------------+---------------+
| Field | Type |
+--------------------------+---------------+
| g_id | int(10) |<- the user group's ID.
| group_name | varchar(255) |<- the name of the user group
+--------------------------+---------------+
Sample users table structure
+--------------------------+---------------+
| Field | Type |
+--------------------------+---------------+
| id | int(10) |<- the user ID
| username | varchar(255) |<- the username
| usergroup | int(10) |<- ID of the user group the user is in
+--------------------------+---------------+
I have no idea what I have missed - but then again, I am very new to more complex queries (if you can call it that).
Any help would be very appreciated!
You want a left join, and you're doing an inner join:
SELECT
g.*,
count(u.username) as total,
u.usergroup
FROM
usergroups as g
left join users as u on
g.u_id = u.usergroup
GROUP BY
g.u_id,
g.group_name
Now that I have your attention, I'd like to take a minute to discuss what join conditions are. See, when you're first learning MySQL, they teach you the syntax you use. And hey, it works great, for certain sets of problems. Unfortunately, it causes you to equate "join condition" with "where predicate," and that's a problem.
In this case, we're saying, "Hey, MySQL, grab me all the stuff out of the usergroups table, and try to find a match to the users table where the u_id column from usergroups equals the usergroup column from users. If you can't find anything, that's okay, bring the usergroup back anyway, and just null out the columns that users brings to the table."
Previously, you were saying, "Hey, MySQL, grab me all the stuff out of the usergroups and the users table, but only where the u_id column from usergroups matches the usergroup column from users."
If you had done it with inner join syntax, like so:
SELECT
g.*,
count(u.username) as total,
u.usergroup
FROM
usergroups as g
inner join users as u on
g.u_id = u.usergroup
GROUP BY
g.u_id,
g.group_name
You would have been saying, "Hey, MySQL, grab me everything from the usergroups table, and then go find everything in the users table where u_id equals usergroup. If you don't find a match, I don't want to see that usergroup show up in the results.
So, to be clear, the where predicates filter the result set, whereas the join conditions map one table to another.
You need to use a LEFT JOIN here instead of your implicit INNER JOIN:
SELECT
g.*,
count(u.username) as total,
u.usergroup
FROM
usergroups as g
LEFT JOIN users as u ON g.g_id = u.usergroup
GROUP BY
g.group_name

mysql query help to find mutual friends on social networking site

I have a database table called users with a primary key of user_id for each user.
I also have a table called friends with two fields, user_id and friend_user_id.
The user_id field is always the lowest of the two user_id's in order to avoid duplicate entries.
Say I have two users in mind, (lets say user id 1 and user id 4 although they could be anything).
How would I return all rows from the users table for users that are friends with user 1 and user 4 (i.e mutual friends)?
I will give you the recipe:
Find all friends of user 1
Find all friends of user 2
Intersect them and the result will be the mutual friends.
Much like this:
UPDATE: Here's the query:
select f.friend_user_id from friends f where f.friend_user_id in (
select friend_user_id from friends where user_id=<id_of_user_a>)
and f.user_id=<id_of_user_b>
The ids returned by above query will be the id of all the users that are mutual friends of user_a and user_b. If you want to get all the details (name, etc) about those users, then do this:
select f.friend_user_id,u.* from friends f inner join users u
on u.user_id=f.friend_user_id
where f.friend_user_id in (
select friend_user_id from friends where user_id=<id_of_user_a>)
and f.user_id=<id_of_user_b>
SELECT friends.friend_user_id FROM user, friends
INNER JOIN friends ON friends.user_id = user.user_id
WHERE user.user_id = 1
AND friend.friend_user_id
IN (SELECT friends.friend_user_id
FROM user, friends
INNER JOIN friends ON friends.user_id = user.user_id
WHERE user_id = 4)