【问题标题】:SQL Recursive CTE using two tables使用两个表的 SQL 递归 CTE
【发布时间】:2012-08-18 08:18:00
【问题描述】:

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

【问题讨论】:

  • 澄清一下,您的示例来自Honey:牛奶 > 密歇根 > 黄油 > 奶油(通过共享)> 威斯康星 > 蜂蜜。对吗?

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


【解决方案1】:

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

【讨论】:

  • 感谢您的代码。看起来我无法在单个查询中执行此操作。因为,我需要从 JAVA 执行这个查询,所以我可能需要把它变成一个 SP。再次感谢。
猜你喜欢
  • 2017-12-11
  • 2022-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-25
  • 1970-01-01
相关资源
最近更新 更多