繁体   English   中英

多对多表的递归查询

[英]Recursive query from a many-to-many table

在A到B的多对多映射表中,说有一个初始条件f(A, B) -> bool ,该映射表中的几对(A,B)满足。

问题是选择所有对,其中对中的A出现在满足条件的集合中,或对中的B出现在满足条件的集合中。 然后继续以这种方式扩展选择集,直到不再添加其他不同的对为止,以便最后,选择包含所有对,您可以从中“走动”到满足初始条件的对。

例:

A_id    B_id
------------
 A1      B1
 A1      B3
 A2      B1
 A2      B2

假设对(A2,B1)和(A2,B2)满足f ,而对(A1,B1)和(A1,B3)不满足。 我需要返回的集合包含所有四对,因为B1出现在满足f的集合中(因此我们包括(A1,B1)),而A1现在出现在成长的集合中(因此我们包括(A1,B3)) 。

做此服务器端的正确方法是什么? 在服务器上执行此操作是否比在客户端上存储一些中间结果并在几个“增量”查询中执行递归更好? 当行数很大时,答案如何变化?

(我需要在SQL Server中执行此操作,但这对于问题不是必需的。)

伪查询语言的示例解决方案:

declare @results table(A_id, B_id)

-- initial set, satisfying the condition
insert into @results -- adds (A2, B1) and (A2, B2)
select A_id, B_id from mapping m where f(A_id, B_id) == true

-- first round of recursion
insert into @results
select m.A_id, r.B_id from mapping m -- adds (A1, B1)
join @results r on r.B_id = m.B_id
insert into @results
select r.A_id, m.B_id from mapping m
join @results r on r.A_id = m.B_id

-- second round of recursion
insert into @results
select m.A_id, r.B_id from mapping m
join @results r on r.B_id = m.B_id
insert into @results
select r.A_id, m.B_id from mapping m -- adds (A1, B3)
join @results r on r.A_id = m.B_id

如果添加第三列以在表中提供f值,则可以使用此查询。

with CTE as 
(
    Select A_ID as Node, Path = CAST(a_id as nvarchar(max))
    from Link
    where f = 1

    UNION

    Select B_ID as Node, Path = CAST(B_ID as nvarchar(max))
    from Link
    where f = 1

    UNION ALL

    Select L.B_ID, CTE.Path + '-' + L.B_ID
    from CTE inner join Link L ON CTE.node = L.A_ID
    where CTE.path not like '%' + L.B_ID +'%'

    UNION ALL

    Select L.A_ID, CTE.Path + '-' + L.A_ID
    from CTE inner join Link L ON CTE.node = L.B_ID
    where CTE.path not like '%' + L.A_ID +'%'
)
select distinct Node from CTE

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM