2013-06-19 44 views
3

我店像這樣簡單的社交圖信息:通過在一個SQL數據庫中的社交圖遍歷

People (PersonId bigint, Name nvarchar) 
Relationships (From bigint, To bigint, Title nvarchar) 

所以數據看起來是這樣的:

People 
1, John Smith 
2, Joan Smith 
3, Jack Smith 

Relationships 
1, 2, Spouse 
1, 3, Parent 
2, 3, Parent 

注意關係的標題是正常化的:所以沒有「丈夫」和「妻子」,只有「配偶」,這也避免需要創建兩個單獨的關係形成相同的鏈接,這同樣適用於「父」而不是「兒子」或「女兒」。

問題是你如何迭代整個連接圖(即只返回一個家族),例如,找到兄弟姐妹而不需要創建顯式兄弟關係條目。節點不一定需要以任何特定順序返回。我可能也想只返回距給定起始節點最多N度的節點。

我知道你可以在最近的SQL語言版本中使用一些新的技巧來做遞歸SQL SELECT語句,但這不一定是遞歸操作,因爲這些關係可以表示循環的非方向圖(想想「朋友」是作爲關係添加)。你如何在SQL中做到這一點?

+0

您正在使用哪個數據庫? – beny23

+0

MS SQL Server 2012,謝謝! – Dai

+0

非常有趣的問題。你能詳細說明你確切的問題嗎? 你的問題可以是「從人物和關係中找到兄弟姐妹」。 如果可能,你能告訴我們一個你期望的結果集嗎? – naota

回答

2

非常酷的問題。雖然它是一個社交網絡圖,但它仍然是一個分層問題,即使層次結構可以在邏輯上轉變成一個互連網絡。在MSSQL中,您仍然希望使用WITH子句執行遞歸查詢,唯一的區別是由於需要使用多個互連來確保唯一結果,請使用DISTINCTWHERE條件中的IN子句。

這工作:

DECLARE @PersonID bigint; 
SET @PersonID = 1; 

WITH RecurseRelations (PersonID, OriginalPersonID) 
AS 
(
    SELECT PersonID, PersonId OriginalPersonID 
    FROM People 

    UNION ALL 

    SELECT ToPersonID, RR.OriginalPersonID 
    FROM Relationships R 
        INNER JOIN 
      RecurseRelations RR 
        ON 
       R.FromPersonID = RR.PersonID 
) 
SELECT PersonId, Name 
FROM People 
WHERE PersonId IN 
     (    
      SELECT PersonID 
      FROM RecurseRelations 
      WHERE OriginalPersonID = @PersonID 
     ) 

這裏有更多的關係比你原本和整個家庭其他一些測試數據,以確保它不會拿起超過預期。

create table People (PersonId bigint, Name nvarchar(200)); 
create table Relationships (FromPersonID bigint, ToPersonID bigint, Title nvarchar(200)); 

insert into People values (1, 'John Smith'); 
insert into People values (2, 'Joan Smith'); 
insert into People values (3, 'Jack Smith'); 
insert into People values (4, 'Joey Smith'); 
insert into People values (9, 'Jaime Smith'); 

insert into People values (5, 'Edward Jones'); 
insert into People values (6, 'Emma Jones'); 
insert into People values (7, 'Eva Jones'); 
insert into People values (8, 'Eve Jones'); 

insert into Relationships values (1, 2, 'Spouse'); 
insert into Relationships values (1, 3, 'Parent'); 
insert into Relationships values (2, 3, 'Parent'); 
insert into Relationships values (3, 4, 'Child'); 
insert into Relationships values (2, 4, 'Child'); 
insert into Relationships values (4, 9, 'Child'); 

insert into Relationships values (5, 6, 'Spouse'); 
insert into Relationships values (5, 7, 'Parent'); 
insert into Relationships values (6, 7, 'Parent'); 
insert into Relationships values (5, 8, 'Child');