我有两个表,一个是产品客户映射,另一个是产品共享表。使用SQL递归CTE,给定一个产品,我试图找到所有链接为链的产品,映射到客户之间。此外,如果产品与其他产品共享,我也需要将其包含在链中。希望我的例子比描述更有意义
Product Customer Table
Product Customer
Milk Illinois
Milk Michigan
Butter Michigan
Cream Wisconsin
Honey Wisconsin
Cheese Minnesota
Product Sharing Table
Product SharedProduct
Butter Cream
Cream Cheese
对于上述数据,假设我的输入产品是牛奶,那么结果集应该包括所有产品 - 牛奶,黄油,奶油,蜂蜜和牛奶。起司。这里是奶油和奶油奶油奶酪通过产品分享表链接。
我当前的SQL看起来像这样,但实际上并没有超过一个级别。
WITH Product_CTE AS
(
SELECT DISTINCT [Product] FROM ProductCustomer
WHERE [Product] IN (SELECT DISTINCT p2.[Product]
FROM ProductCustomer p1 INNER JOIN ProductCustomer p2
ON p1.[Customer] = p2.[Customer] WHERE p1.[Product] = 'Milk')
UNION ALL
SELECT [SharedProduct] FROM ProductSharing b
INNER JOIN Product_CTE p ON p.[Product] = b.[Product]
)
Select [Product] from Product_CTE
答案 0 :(得分:0)
CTE存在多个UNION
的问题。虽然它有可能,但它对我不起作用。
另一种方法是使用一个循环,当没有更多行添加到工作表时停止:
declare @ProductCustomers as Table ( Product VarChar(16), Customer VarChar(16) )
insert into @ProductCustomers ( Product, Customer ) values
( 'Milk', 'Illinois' ),
( 'Milk', 'Michigan ' ),
( 'Butter', 'Michigan ' ),
( 'Cream', 'Wisconsin' ),
( 'Honey', 'Wisconsin' ),
( 'Cheese', 'Minnesota' )
declare @ProductSharing as Table ( Product VarChar(16), SharedProduct VarChar(16) )
insert into @ProductSharing ( Product, SharedProduct ) values
( 'Butter', 'Cream ' ),
( 'Cream', 'Cheese ' )
declare @TargetProduct as VarChar(16) = 'Milk'
declare @ProductChain as Table ( Product VarChar(16) )
insert into @ProductChain ( Product ) values ( @TargetProduct )
declare @NewRows as Int = 1
while @NewRows > 0
begin
set @NewRows = 0
-- Add products shared by the same customer.
insert into @ProductChain
select PCR.Product
from @ProductCustomers as PCL inner join
@ProductCustomers as PCR on
-- Shared customer.
PCR.Customer = PCL.Customer and
-- Different product.
PCR.Product <> PCL.Product
where not exists ( select 42 from @ProductChain where Product = PCR.Product )
set @NewRows = @NewRows + @@RowCount
-- Add products linked through the product sharing table.
insert into @ProductChain
select PS.SharedProduct
from @ProductSharing as PS inner join
@ProductChain as PC on PC.Product = PS.Product
where not exists ( select 42 from @ProductChain where Product = PS.SharedProduct )
set @NewRows = @NewRows + @@RowCount
end
select Product
from @ProductChain
order by Product
这里假设@ProductSharing
表是单向的。