递归自联接以解压缩分发列表

时间:2018-08-15 12:46:52

标签: sql sql-server

我有一个“列表”表,该表包含2列[ListName]和[MemberName],但是成员名称可以是一个人的名字,也可以是另一个列表(嵌套列表)的名称-数据来自外部来源。

CREATE TABLE Lists
(
ListName varchar(255) NOT NULL,
MemberName varchar(255) NOT NULL
)

没有什么可以阻止列表名称的最终“自我引用”

例如

List01 - Contains List02
List02 - Contains List03 and List04 
List03 - Contains List01

我要找的是

1)一种确定是否有嵌套的自引用的方法

2)如果没有,则返回包含所有嵌套列表的单个合并列表

例如

List01 - List02Member01
List01 - List01Member02
List01 - List01Member03
List01 - List02Member01
List01 - List02Member02
List01 - List03Member01
List01 - List04Member01
List02 - List02Member01
List02 - List02Member02
List02 - List03Member01
List02 - List04Member01

等等。

即展开嵌套的每个列表的完整展开列表

我怀疑CTE会参与某个地方的答案,但是目前,我甚至还在努力寻找如何开始这一答案的机会。

示例源数据-在“列表”表中(已混淆)

ListName        MemberName
========        ==========
Domain\List01   Domain\Member01
Domain\List01   Domain\Member02
Domain\List01   Doman\Member03
Domain\List02   Domain\Member04
Domain\List02   Domain\Member02
Domain\List02   Domain\List03
Domain\List02   Domain\List04
Domain\List03   Domain\Member05
Domain\List03   Domain\Member06
Domain\List03   Domain\List05
Domain\List04   Domain\Member07
Domain\List04   Domain\Member08
Domain\List05   Domain\Member09
Domain\List05   Domain\List01
Domain\List01   Domain\List02

2 个答案:

答案 0 :(得分:0)

我的头顶上

要检测直接的自我参考:

select l1.listname, l1.membername from lists l1
where exists (select * from lists l2 where l1.membername = l2.listname)

如果这行得通,那么该查询未返回的任何内容都可以用来产生第二个结果。

答案 1 :(得分:0)

我认为您正在寻找类似的东西。

;WITH list_structure AS
(
    SELECT CAST(l1.listname AS NVARCHAR(255)) AS list_path,
    l1.listname,
    CAST(l1.membername AS NVARCHAR(255)) AS membername
    FROM lists l1
    WHERE l1.listname NOT IN (SELECT membername FROM lists)
UNION ALL
    SELECT CAST(list_structure.list_path + '/' + l.listname AS NVARCHAR(255)), 
    l.listname,
    l.membername
    FROM lists l
    INNER JOIN list_structure
    ON l.listname = list_structure.membername
)

SELECT list_path + '/' + list_structure.membername FROM list_structure
WHERE list_structure.membername NOT IN (SELECT listname FROM lists)