Daniel Iftimie
Daniel Iftimie

Reputation: 233

Get users which I have friends in common

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

Answers (3)

LHA
LHA

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

Thorsten Kettner
Thorsten Kettner

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

Gordon Linoff
Gordon Linoff

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

Related Questions