2013-12-18 119 views
0

我創造一種社會網站與朋友和我有用戶和朋友的關係表SQL朋友,關係單向/雙向系統

FRIENDS 
id   iduser  idfriend 
0    44   56 
1    44   102 
2    10   66 
3    10   85 
4    44   10 
5    10   44 
6    56   44 

LOGIN 
id   jmeno    email  isonline 
44   john   [email protected]   1 
10   joe   [email protected]   1 
185  mark   [email protected]    0 

當用戶從服務器他的朋友聯繫,他要求這在線和我用這個SQL命令爲

SELECT u.id, 
     jmeno, 
     email 
    FROM friends f 
     INNER JOIN login u 
      ON f.idfriend = u.id 
WHERE f.iduser = 44 
     AND u.online =1 

但我意識到,這是不是因爲當用戶44和用戶10希望成爲朋友,必須有既像關係的正確解決方案:

44 - 10 
    10 - 44 

我只想從數據庫中的一行中選擇關係 所以在iduser和idfriend eithe中找到id。現在我在這裏使用這個單向關係sql。

+0

此方法在存儲空間方面可能效率不高,但至少您可以通過「朋友」表中的單個字段「iduser」爲用戶找到朋友。如果每對朋友只有一行,那麼您還需要檢查「idfriend」,這將需要更多時間。 – athabaska

回答

0

幾種方法來做到這一點。一個是做內部加入一個or,讓你在iduseridfriend加盟:

select 
    u.* 
from 
    login u 
    join friends f 
    on (u.id = f.iduser 
     and f.idfriend = 44) 
    or (u.id = idfriend 
     and f.iduser = 44) 
where 
    u.id != 44; 

另一種方法是創建一個用於創建的的列表所有雙向朋友關係的子查詢,然後從中選擇:

select 
    * 
from 
(select 
     iduser, 
     u.* 
    from 
     friends f 
     inner join login u on f.idfriend = u.id 
    union 
    select 
     idfriend, 
     u.* 
    from 
     friends f 
     inner join login u on f.iduser = u.id) q 
where 
    q.iduser = 44 
    and q.isonline = 1 

您沒有指定您正在使用的數據庫引擎 - 如果你正在使用一個支持的CTE(Oracle或SQL Server爲例),子查詢中可以代替完成CTE。

第二種方法更耗費資源,但只需要對代碼進行一次更改即可選擇不同的ID。

所有三個查詢都在這SQLFiddle,但我刪除了現有的雙向友誼,以說明邏輯。

0

你目前的架構不一定是壞事。這就是我設計這種關係的方式。

Friends表是一個標準的交叉引用表。如果朋友關係被切斷,你需要清理雙方,但這很容易。它允許您加入一列,id,並且一次獲得正確的idfriend。這也使得保證唯一性的一個容易的約束。 (10,44)意思是10個想成爲44的朋友,但如果(44,10)不在那裏,那麼可能有44個人不想和10成爲朋友。但是也許也許這不是業務需求。

如果您希望(10,44)等同於(44,10),那麼在創建關係時,您必須添加額外的查詢以查看雙方並確保現有關係不存在。

您可以在連接子句中使用OR或使用UNION進行此操作。喬的代碼看起來不錯。您也可以在這裏查看視圖(或索引視圖)。