简体   繁体   中英

improving a friends list query : counting the mutual friends

i have two tables in my database one is to keep users info (users_table ) and the other one keeps track of the friends

users_table:

id    username      avatar  
1         max       max.jpg  
2         jack      jack.jpg  

friends_table :

id    u1_id      u2_id  
1         1          2  
2         1          3  

in every user profile i show his/her friends list

here is my query

select u.id,
    u.username,
    u.avatar
from friends_table f
join users_table u on f.u1_id = u.id || f.u2_id = u.id
where u.id <> $profile_id
    and (f.u1_id = $profile_id || f.u2_id = $profile_id)

this query selects friends of the profile owner ($profile_id)

and join them with the user table to get each friend username and avatar

now i want to count the mutual friends between each friend and the profile owner is it possible to this in one query or should i do some long and probably slow query like this for each founded friend( it's just a example and it might have some syntax error ):

       foreach ( $friends_list_query_resul as $qr ){
       $friend_id = $qr['id'];

       $mutual_count = mysql_query
    ( "select count(*) from friends_table where 
    ($u1_id = $friend_id || $u2_id = $friend_id )
               && 


    ( $u1_id IN ( SELECT `u1_id`,`u2_id` from friends_table where
     ($u1_id = $profile_id || $u2_id = $profile_id ) )

||

      $u2_id IN ( SELECT `u1_id`,`u2_id` from friends_table where
     ($u1_id = $profile_id || $u2_id = $profile_id ) )


       ")
        }

Your first query could also be written as:

select distinct u.id,
        u.username,
        u.avatar
    from users_table u where u.id in 
        (select case when u1_id=$profile_id then u2_id else u1_id end 
        from friends_table f where case when u1_id=$profile_id 
        then u1_id else u2_id end =$profile_id);

The mutual friends query can be written as a single query in similar fashion:

select u.id, (select count(f.id) from friends f where 
    case when f.u1_id=u.id then u2_id else u1_id end in 
        (select distinct case when u1_id=$profile_id then u2_id else u1_id end 
        from friends where case when u1_id=$profile_id then u1_id else u2_id 
        end =$profile_id) 
    and u1_id=u.id or u2_id=u.id and 
    (u1_id <> $profile_id and u2_id <> $profile_id)) 
as mutual_frnds from user u where u.id <> $profile_id;

but you might want to performance test either of them before using.

All you need is one query:

select id, username, avatar, -- ...
(
  select count(*)
  from friends_table f1
  inner join friends_table f2 on f1.u2_id = f2.u1_id and f2.u2_id = f1.u1_id
  where f1.u1_id = users_table.id
)
as mutual_friend_count
from users_table

The meaning of the subquery is:

Give me the count of the "friend of a friend" relations the user participates in, such that the target of the first friend relation is the source of the second friend relation, and the target of the second friend relation is the source of the first one.

First, I do not understand why so complicated query to retrieve the user's friends... It should be simply achieved by this query:

select u.id,
    u.username,
    u.avatar
from friends_table f
left join users_table u on f.u2_id = u.id
where f.u1_id = $profile_id

Explain: the logged in user is the one whose id is the same as f.u1_id . Therefore we only select friends whose ids are in f.u2_id .

Then, to count the mutual friends of my friends we can use query like this:

select count(*) as mutual_count, f.u1_id as mutual_friend_id
from friends_table f
where f.u1_id IN (select f.u2_id from friends_table where f.u1_id = {$profile_id})

where $profile_id is the ID of logged in user...

Is this correct?

i've decided to add two rows for each friend relation to the table .

id    u1_id      u2_id  
1         10         20  
2         20         10

it makes the process easier and faster .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM