SQL递归CTE使用两个表

时间:2012-08-22 20:40:06

标签: sql sql-server-2005 common-table-expression recursive-query

我有两个表,一个是产品客户映射,另一个是产品共享表。使用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

1 个答案:

答案 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表是单向的。