2015-03-13 72 views
2

我在論壇中創建一個朋友系統。按朋友系統搜尋 - 朋友系統Mysql PHP

我正在經歷一段艱難的時間,試圖弄清楚我將如何抓取用戶並通過mutual_friend計數進行訂購。

我正在嘗試構建一個顯示推薦朋友列表的頁面。

這裏是我的表的結構:

users table 
----- 
user_id | name | 

friends table 
----- 
friend_id | from_id | to_id 

這裏是正在發生的事情的一個例子。

假設有總共ABCDEF = 6人在現場。

  • ABC都是我的朋友。
  • DE依次是B的朋友。
  • D也是C一個朋友,但EC的朋友。
  • F不是該網站任何人的朋友。

因此,從以上數據看起來DE是我(A)共同的朋友。 F不是是我的共同朋友。

由於DBCE的朋友是朋友只B

  • AD具有2共同的朋友。
  • AE1共同的朋友。
  • AF0共同的朋友。

現在,如果我想搜索(記得我是A)的人誰不是我的朋友,我可以這樣做:

$myfriends = "2,3"; //putting all my friends in a variable

SELECT * FROM users WHERE user_id NOT IN($myfriends)

但它會產生在條款user_id ASC。如何在DESC中搜索mutual_friends。 ?

Auser_id = 1

人有更多共同的朋友至上

請誰能告訴我我該怎麼辦呢?我在這裏呆了很久。我搜索了很多東西,但無法弄清楚。

+0

你可以請包括你試過的代碼嗎?就目前情況來看,要弄清楚問題出在哪裏有點困難。 – Phrancis 2015-03-13 18:47:27

+0

@Phrancis問題是我怎樣才能通過'no_of_mutual_friends'命令'DESC''select'。 – 2015-03-13 18:51:15

+0

哦。讓我寫一些東西然後 – Phrancis 2015-03-13 18:57:27

回答

6

此查詢將考慮到關係的相互關係,因此,如果關係變爲「從A到B」或「從B到A」,它仍然會返回預期結果並不重要。因此,考慮表是這樣的:

CREATE TABLE people 
    (`id` int, `name` varchar(1)) 
; 

INSERT INTO people 
    (`id`, `name`) 
VALUES 
    (1, 'A'), 
    (2, 'B'), 
    (3, 'C'), 
    (4, 'D'), 
    (5, 'E'), 
    (6, 'F') 
; 


CREATE TABLE friends 
    (`id` int, `personId1` int, `personId2` int) 
; 

INSERT INTO friends 
    (`id`, `personId1`, `personId2`) 
VALUES 
    (1, 1, 2), 
    (2, 3, 1), 
    (3, 2, 4), 
    (4, 5, 2), 
    (5, 3, 4) 
; 

我相信這是設置爲你所描述:A和B是朋友,A和C是朋友(注意反向關係),B和d是朋友,E和B是朋友(另一種倒轉的關係),C和D是朋友。

假設你想要的人的ID是@personId:

SELECT StrangerId, COUNT(MutualFriendId) AS TotalMutualFriends 
FROM 
(SELECT 
    CASE WHEN f.personId2 = mf.friendId THEN f.personId1 ELSE f.personId2 END AS StrangerId, 
    CASE WHEN f.personId1 = mf.friendId THEN f.personId1 ELSE f.personId2 END AS MutualFriendId 
FROM 
(SELECT 
    CASE 
    WHEN personId1 = @personId THEN personId2 
    ELSE personId1 
    END AS friendId 
FROM friends 
WHERE personId1 = @personId OR personId2 = @personId) AS mf 
INNER JOIN friends f 
ON (personId1 != @personId AND personId2 = mf.friendId) 
    OR (personId1 = mf.friendId AND personId2 != @personId) 
) AS totals 
GROUP BY StrangerId 
ORDER BY TotalMutualFriends DESC; 

結果@personId = 1:

StrangerId TotalMutualFriends 
4   2 
5   1 

And here is a SQLFiddle證明(我無法得到它允許我設置一個變量,所以它有一個1)。

+0

它似乎是一半的正確答案但是,* dont在哪裏取得我的朋友*聲明,即'user_id NOT IN($ myfriends)'去? – 2015-03-13 19:39:22

+0

'2'是'1'的朋友,'3'是'1'的朋友我說我不想只顯示'朋友''非朋友' – 2015-03-13 19:44:53

+0

你做了相反的事情保羅你把我朋友取了'B'和'C'但我想在mutual_count中獲得'D','E'和'F'。你在上面的查詢中相互統計是好事! @paulGriffin – 2015-03-13 20:11:57

2

事情是這樣的,也許:

Select user_id, friends.to_id, count(friend_of_friend.to_id) 
from users left outer join 
    friends on users.user_id = friends.from_id left outer join 
    users as friend_user on friends.to_id = friend_user.user_id left outer join 
    friends as friend_of_friend on friend_user.user_id = friend_of_friend.from_id and friend_of_friend.to_id in (select to_id from friends where from_id = users.user_id) 
Group by USER_ID, friends.to_id 
Order by 3 

編輯爲清楚: 此查詢的邏輯依賴於同一個表中多次加入。前兩個連接非常直接,我們從一張用戶表開始,然後加入將每個用戶與所有朋友關聯的朋友表。但是,我們再次加入用戶表,但這次使用「到」列 - 我們獲取每個朋友的用戶信息。由於我們在查詢中不能有兩次相同的表名,我們給它一個「friend_user」的別名。然後我們再根據friend_user表中的id加入朋友表 - 這給了我們每個原始用戶朋友的所有朋友。然後,我們將使用「Friend_of_friend.to_id in ...」中的朋友的朋友限制爲將朋友的朋友與所有原始用戶朋友的列表進行比較,這些朋友由子查詢引入 - 僅部分括在括號內的「in」之後。

+0

可以將連接更改爲內連接以提高效率,具體取決於您希望得到的結果。 – TPhe 2015-03-13 19:07:37

+0

字段列表中的'user_id'字段不明確 – 2015-03-13 19:13:32

+0

您擊敗了我。 – 2015-03-13 19:13:49