Reputation: 233
There are 2 sql tables:
1) "users" with the following structure and data:
user_id, user_name
1, John
2, Mike
3, Chris
4, Paul
5, Kelly
6, Kevin
2) "userfriends" which cotains friendship relations, with the following structure and data:
userfriends_user_id, userfriends_friend_id
1, 2 => [ John is friend with Mike ]
2, 3 => [ Mike is friend with Chris]
2, 4 => [ Mike is friend with Paul ]
5, 1 => [ Kelly is friend with John]
6, 5 => [ Kevin is friend with Kelly]
I want to make a SELECT (user_name, user_id) to get those users where John have common friends with, so the output should be Chris, Paul, Kevin. Can this be done in only ONE select statement ?
Upvotes: 0
Views: 114
Reputation: 9655
TEST this query:
SELECT * FROM users
WHERE user_id IN
(
SELECT uf.userfriends_friend_id AS CommonId
FROM userfriends uf,
(
SELECT uf2.userfriends_friend_id
FROM userfriends uf2
WHERE uf2.userfriends_user_id = 1
) A
WHERE uf.userfriends_user_id = A.userfriends_friend_id
UNION
SELECT uf.userfriends_user_id AS CommonId
FROM userfriends uf,
(
SELECT uf2.userfriends_user_id
FROM userfriends uf2
WHERE uf2.userfriends_friend_id = 1
) A
WHERE uf.userfriends_friend_id = A.userfriends_user_id
)
I tested SQLfiddle provided by @Thorsten Kettner. It works. Output is correct. Thanks @Thorsten Kettner!
Upvotes: 0
Reputation: 95090
Well, I still don't know if I am thinking too complicated right now. Here is what I've come up with:
select * from users
where user_id in
(
select user1_id
from
( -- users except John and their friends (again except John)
select userfriends_user_id as user1_id, userfriends_friend_id as user2_id
from userfriends where userfriends_user_id != 1 and userfriends_friend_id != 1
union
select userfriends_friend_id as user1_id, userfriends_user_id as user2_id
from userfriends where userfriends_user_id != 1 and userfriends_friend_id != 1
) others
where user2_id in
( -- friends of John's
select userfriends_user_id from userfriends where userfriends_friend_id = 1
union
select userfriends_friend_id from userfriends where userfriends_user_id = 1
)
);
Here is the SQL fiddle: http://sqlfiddle.com/#!2/338d87/1.
Upvotes: 0
Reputation: 1270993
You can do this by getting all the friends of your friends. This requires a join from the userfriends
table back to itself.
Then, just look at the the "friends of friends" that appear more than once. You can do this with group by
and having
:
select uff.userfriends_friend_id
from userfriends uf join
userfriends uff
on uf.userfriends_friend_id = uff.userfriends_user_id
where uf.userfriends_user_id = 1
group by uff.userfriends_friend_id
having count(*) > 1;
Upvotes: 1