0

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

对于上述数据,假设我的输入产品是牛奶,那么结果集应该包括所有产品 - 牛奶、黄油、奶油、蜂蜜和奶酪。在这里,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
4

1 回答 1

0

CTE 有多个UNIONs 的问题。尽管有可能,但它对我不起作用。

另一种方法是使用在没有更多行添加到工作表时停止的循环:

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

于 2012-08-22T21:34:38.417 回答