迭代SQL数据库中的社交图

时间:2013-06-19 07:34:09

标签: sql recursion graph sql-server-2012

我存储简单的社交图形信息,如下:

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语句,但这不一定是递归操作,因为这些关系可以表示循环非方向图(想想是否添加了“Friend”)作为一种关系)。你会如何在SQL中做到这一点?

1 个答案:

答案 0 :(得分:2)

非常酷的问题。虽然它是一个社交网络图,但它仍然是一个分层问题,即使层次结构可以在逻辑上变成互连网络。在MSSQL中,您仍然希望使用WITH子句来执行递归查询,唯一的区别是,由于需要多个互连,您需要使用DISTINCT或使用{{来确保唯一结果IN条件中的1}}子句。

这有效:

WHERE

这里有一些测试数据与你原来的关系比其他家庭更多,以确保它没有超出预期。

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
        )