在As到Bs的多对多映射表中,假设有一个初始条件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
答案 0 :(得分:0)
如果添加第三列,在表中给出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