3

我像这样存储简单的社交图信息:

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 中做到这一点?

4

1 回答 1

2

很酷的问题。虽然它是一个社交网络图,但它仍然是一个层次问题,即使层次结构在逻辑上可以变成一个互连网络。在 MSSQL 中,您仍然希望使用WITH子句进行递归查询,唯一的区别是,由于需要多重互连来确保结果的唯一性,无论是在条件中使用子句DISTINCT还是使用子句。INWHERE

这有效:

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');
于 2013-07-05T13:57:17.237 回答