我有一个产品表(tProduct)和一个产品链接表(tProductLink),以便在产品之间建立链接。给定ProductID和ProductLinkID,我需要获取所有相关的tProduct.ID记录。
在下面的示例表(tProductLink)中,将返回所有ID。请注意,无法创建递归链接;在下表中给出第一行的情况下,不能有ProductID为31563且ProductID为28818的行。
所以说我搜索与第4行,ProductID 137902和LinkProductID 410901中的链接相关的所有产品。给该链接,它应该返回所有六行。
以下是数据的示例。
我尝试了各种技术,如递归CTE和使用“交叉应用”调用表函数,但我无处可去。
这是我尝试过的最后一个解决方案之一,最终没有按照评论中的说明退回所有产品。
declare @ProductID int, @ProductLinkID int
select @ProductID = 137902
select @ProductLinkID = 410901
;with p1 as
(
select ProductID, ProductLinkID
from tProductLink
where ProductID = @ProductID and ProductLinkID = @ProductLinkID
union all
select tProductLink.ProductID, tProductLink.ProductLinkID
from tProductLink
join p1 on p1.ProductLinkID = tProductLink.ProductID
where not (tProductLink.ProductID = @ProductID and tProductLink.ProductLinkID = @ProductLinkID)
)
select distinct ProductID from p1
union
select ProductLinkID from p1
答案 0 :(得分:1)
您从一个ID开始。这可以在第二个表中的多行ProductLinkId
或ProductId
中。您可以在第二个表中再次查找相应的ID。
这会要求递归查询,您始终可以收集所有相应的ID。不幸的是,SQL Server在递归查询中不支持DISTINCT
,因此会多次查找相同的ID。 SQL Server也不会阻止循环(但是会失败),因此我们必须通过记住已经找到的ID来防止它们。理想情况下,这将使用我们填充的数组或集合来完成,但SQL Server不支持这样做,因此我们必须构建一个字符串。
完整的查询:
with cte(id, seen) as
(
select 28520 as id, cast('/28520/' as varchar(max)) as seen from t1
union all
select case when cte.id = t2.productid then t2.linkproductid
else t2.productid end as id,
cte.seen + cast(case when cte.id = t2.productid
then t2.linkproductid
else t2.productid end as varchar(max)) + '/'
from cte
join t2 on cte.id in (t2.productid, t2.linkproductid)
and charindex('/' + cast(case when cte.id = t2.productid
then t2.linkproductid
else t2.productid end as varchar(max))+ '/', cte.seen) = 0
)
select distinct id from cte
option (maxrecursion 1000);
Rextester演示:http://rextester.com/WJJ78304