MichaelH MichaelH - 10 days ago 6
MySQL Question

Mutual Friends - MySQL

I am trying to develop a function which shows me friends of friends, and how many mutual friends I have with those users. So far, I have been able to do the functions separately but not together.

Here is the main view I am using called userfriends. Where user1 is the first user and user2 is the friend.

enter image description here

This is the function I have developed to see mutual friends between two users

SELECT id FROM users
WHERE id IN (
SELECT user2 FROM userfriends WHERE user1 = me
) AND id IN (
SELECT user2 FROM userfriends WHERE user1 = second
)


Users is a main table which can link the user id found in the userfriends table to information about the user. Me and second are variables in the stored procedure which emulate the search for first and second users. This function works to plan.

The second function I have is to see all the users who are friends with my friends, but not with me.

SELECT user2 AS id
FROM userfriends
WHERE user1 IN (
#Selects my friends
SELECT user2 FROM userfriends
WHERE user1 = me
)
AND user2 <> me #Makes sure is not me
AND user2 NOT IN ( #Makes sure not already friend
SELECT user2 FROM userfriends
WHERE user1 = me
)


Again, all working to plan and me represents the user id. This will return a list of all my friends friends.

What I want to be able to get instead of a list of mutual users, or a list of my friends friends is:

A table which has my friends friend user ID and how many mutual friends me and that user shares. Etc: user: 1, friends_in_common: 103. If I'm not clear enough please ask and I will try and make it clearer. The two functions do it by themselves, but I'm just not sure how to merge it together.

Answer
-- use a self-join of userfriend*userfriend
-- to find all the friends that moi&toi have in common
-- , and count them.
-- (optionally) suppress the rows for (toi<=moi)
-- , because there are basically the same as the corresponding rows with
-- (toi>moi)
-- -----------------------------------
SELECT DISTINCT 
   uf1.user1 AS moi
   , uf2.user1 AS toi
   , COUNT(*) AS cnt
   FROM userfriend uf1
   JOIN userfriend uf2 ON uf1.user2 = uf2.user2
   WHERE uf1.user1 < uf2.user1 -- Tie breaker, symmetry remover
   GROUP BY uf1.user1, uf2.user1
   ;