2012-05-17 51 views
6

我在我的數據庫中的兩個表一個是保持用戶信息(users_table) ,另一種跟蹤的朋友改善好友列表查詢:數着共同的朋友

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 

在每個用戶的個人資料我展示他/她的朋友列表

這裏是我的查詢

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) 

此查詢選擇配置文件所有者的朋友($ PROFILE_ID)

,並與用戶表讓每個朋友的用戶名和頭像

現在我想加入他們的行列計算每個朋友和個人資料所有者之間的共同朋友是否可以在一個查詢中做到這一點,或者我應該爲每個創建的朋友做一些這樣的很長很可能很慢的查詢(這只是一個例子,它可能有一些語法錯誤):

 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)) 


     ") 
     } 
+9

不怕大寫字母...... – Lix

+0

我的建議是提取每個ID的朋友列表,並用php做出常見的朋友之間的匹配,當涉及操縱數據時,MSQL比其他編程語言慢。 – jcho360

+0

@ jcho360不好的建議。數據庫的規模往往比這種內存方式要好得多。數據庫在處理數據時不會「比其他編程語言慢」,實際上,如果使用正確的話,它們通常要快得多。 –

回答

0

我已經決定爲表中的每個朋友關係添加兩行。

id u1_id  u2_id 
1   10   20 
2   20   10 

它使過程更容易和更快。

+1

哇,不知道回答自己的問題是合法的......無論如何,一定要保存誰要求友誼的信息,以防萬一你需要它 –

0

首先,我不明白爲什麼那麼複雜的查詢,以獲得用戶的朋友......應該通過這個查詢簡單地實現:

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 

說明:登錄的用戶是其ID的一個與f.u1_id相同。因此,我們只選擇其ID爲f.u2_id的朋友。

然後,算我的朋友們共同的朋友,我們可以使用這樣的查詢:

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}) 

其中$ PROFILE_ID是登錄用戶的ID ...

這是正確的嗎?

+0

實際上,關於第一個查詢,'$ profile_id'也可以在'f.u2_id'列 – pomeh

+0

是的當然,因爲它有很多關係,但是當它在'f.u2_id'中時,它意味着我是某個身份爲'f.u1_id'的人的朋友 - 這種關係對我們來說不是問題(或者不應該)只是當我的朋友拿起...而不是我的朋友... – shadyyx

+0

這是不確定的用戶!我認爲這取決於用例。 @max你覺得怎麼樣? – pomeh

1

第一個查詢也可以寫成:

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); 

的共同的朋友查詢可以寫成類似的時尚單查詢:

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; 

,但你可能要性能測試要麼他們之前使用。

+0

我希望不使用子查詢來做到這一點。我要檢查表現並看看。 thanx重播 – max

1

所有你需要的是一個查詢:

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 

子查詢的含義是:

給我計數「朋友的朋友」的用戶參與的關係,使得第一個朋友關係的目標是第二個朋友關係的來源,第二個朋友關係的目標是第一個朋友關係的來源。

+1

thanx,但我認爲這個工作,我不得不改變數據存儲在數據庫中的方式。現在每個用戶都可以在u1_id或u2_id爲每個關係,所以我必須檢查兩個,我不能只是說選擇u1_id。 – max

+0

如果你必須指出相互之間的友誼關係,這意味着你所存儲的友誼關係並不通勤,即如果你是u2的朋友,這並不意味着你是u1的朋友。如果他們不通勤,那麼這個對(u1,u2)與這個對(u2,u1)不是一回事。根據我的看法,friends_table中的一列必須是關係的「來源」,另一列必須是「目標」。我錯過了什麼? –

+0

事情是友誼通勤。如果我請你成爲我的朋友,你接受,你是我的朋友,我是你的朋友。至少這是它在我的代碼 – max