MySQL Query to find friends and number of mutual friends

前端 未结 3 420
盖世英雄少女心
盖世英雄少女心 2020-12-28 11:16

I have looked through the questions but I cant find anything that does exactly what I need and I can\'t figure out how to do it myself.

I have 2 tables, a user table

3条回答
  •  轮回少年
    2020-12-28 12:00

    If A is friend of B, then B is also a friend of A? Wouldn't it be better to use just a link instead of two links (and instead of two rows in friends_links)? Then you have to use two status columns, status1 and status2, and A is friend of B only if status1 = status2 = "a".

    There are many ways to show mutual friends, e.g.:

    SELECT friend_id
    FROM friend_links
    WHERE friend_links.user_id = $user1 or friend_links.user_id = $user2
      AND NOT (friend_links.friend_id = $user1 or friend_links.friend_id = $user2)
    GROUP BY friend_id
    HAVING Count(*)>1
    

    And this query shows for each user and anyone who's not his/her friend:

    SELECT
      users.user_id,
      users.first_name,
      users_1.user_id,
      users_1.first_name
    FROM
      users INNER JOIN users users_1 ON users.user_id <> users_1.user_id
    WHERE
      NOT EXISTS (SELECT *
                  FROM friend_links
                  WHERE
                    friend_links.user_id = users.user_id
                    AND friend_links.friend_id = users_1.user_id)
    

    (The only think I didn't check is the friendship status, but it's easy to add that check).

    I'm still working on it, but it's not easy to combine nicely these two queries togheter. So this isn't exactly an answer, I'm just showing some ideas that i've tried.

    But what do you need exactly? A query that returns every user with anyone who's not his/her friend and the number of friends in common, or is the user_id already given?

    With some code it's not a problem to answer your question... but there has to be a nice way just by using SQL! :)

    EDIT:

    I'm still wondering if there's a better solution to this, in particular the next query could be extremely slow, but it looks like this might work:

    SELECT
      users_1.user_id,
      users_2.user_id,
      Sum(IF(users_1.user_id = friend_links.user_id AND users_2.user_id = friend_links_1.friend_id, 1, 0)) As CommonFriend
    FROM
      users users_1 INNER JOIN users users_2
        ON users_1.user_id <> users_2.user_id,
      (friend_links INNER JOIN friend_links friend_links_1
        ON friend_links.friend_id = friend_links_1.user_id)
    GROUP BY
      users_1.user_id,
      users_2.user_id
    HAVING
      Sum(IF(users_1.user_id = friend_links.user_id AND users_2.user_id = friend_links.friend_id, 1, 0))=0
    

    (as before, i didn't check friendship status)

    If user is given, you could put WHERE users_1.user_id=$user1 but it's better to just leave one user table, and filter the next INNER JOIN whith that user.

提交回复
热议问题