在SQL中实现递归查询

Tej*_*tel 6 sql sql-server recursive-query

我有一个关于使用递归SQL的问题,其中我有以下表结构

产品可以分为多组(为了清楚起见,我不使用int)

CREATE TABLE ProductGroups(ProductName nvarchar(50), GroupName nvarchar(50))

INSERT INTO ProductGroups(ProductName, GroupName) values 
('Product 1', 'Group 1'),
('Product 1', 'Group 2'),
('Product 2', 'Group 1'),
('Product 2', 'Group 6'),
('Product 3', 'Group 7'),
('Product 3', 'Group 8'),
('Product 4', 'Group 6')


+-----------+---------+
|  Product  |  Group  |
+-----------+---------+
| Product 1 | Group 1 |
| Product 1 | Group 2 |
| Product 2 | Group 1 |
| Product 2 | Group 6 |
| Product 3 | Group 7 |
| Product 3 | Group 8 |
| Product 4 | Group 6 | 
+-----------+---------+
Run Code Online (Sandbox Code Playgroud)

现在问题是我想找出所有相关产品,即如果我通过产品1,那么我需要以下结果

+-----------+---------+
|  Product  |  Group  |
+-----------+---------+
| Product 1 | Group 1 |
| Product 1 | Group 2 |
| Product 2 | Group 1 |
| Product 2 | Group 6 |    
| Product 4 | Group 6 | 
+-----------+---------+
Run Code Online (Sandbox Code Playgroud)

所以基本上我想首先找出产品1的所有组,然后为每个组找到所有产品等等......

  1. 产品1 =>第1组,第2组;
  2. 第1组=>产品1,产品2(第1组和产品1已经存在,因此应该避免,否则将进入无限循环);
  3. 第2组=>产品1(已经存在与上述相同);
  4. 产品2 =>第1组,第6组(第1组和第2组已存在)
  5. 第6组=>产品4

Blo*_*ard 3

我认为递归 CTE 不可能实现这一点,因为每个递归定义只允许有一个递归引用。

我确实设法用while循环来实现它,这可能比 cte 效率低:

declare @related table (ProductName nvarchar(50), GroupName nvarchar(50))

-- base case
insert @related select * from ProductGroups where ProductName='Product 1'

-- recursive step
while 1=1
begin

    -- select * from @related -- uncomment to see progress

    insert @related select p.*
    from @related r
    join ProductGroups p on p.GroupName=r.GroupName or p.ProductName=r.ProductName
    left join @related rr on rr.ProductName=p.ProductName and rr.GroupName=p.GroupName
    where rr.ProductName is null        

    if @@ROWCOUNT = 0
        break;

end

select * from @related
Run Code Online (Sandbox Code Playgroud)

您绝对应该小心上述内容 - 在部署之前对实际大小的数据进行基准测试!