SQL Server:表的递归自连接(无WITH子句)

时间:2014-03-25 16:44:55

标签: sql sql-server recursion inner-join

我有下表:

CREATE TABLE routes
(
    ID int identity not null primary key,
    from int,
    to int,
    length int not null
)

我需要拥有从指定ID1ID2的所有路线。

我听说过WITH条款,但根本不满足我。它不允许轻松搜索从ID1ID2的方式,因为它只返回FROMTO值的表格,并且很难搜索所有可能的方式。

我需要像递归内连接这样的东西 - 例如:

SELECT * 
FROM routes r1
INNER JOIN routes r2 ON (r1.to = r2.from AND r2.to <> r1.from AND r1.from = ID1)

它允许我查找包含2条路线的所有方式,从ID1开始,但不是那些去某处然后返回ID1的路线。现在我可以选择所有以ID2结尾的路由(可能是NULL,但可能会出现某些内容)。如果将在ID2处完成路线或路线,我想要打破,如果没有,我想在路线r3内部加入并重复程序,直到找到路线。

我可以在程序和IF条款中执行此操作,但我认为必须有更好的解决方案。

正如我所说,WITH子句不满足我,因为它不会让我轻易找到所有路由,只有一个。

1 个答案:

答案 0 :(得分:1)

  1. 我改变了一些东西,以便更容易玩。例如,避免[from]和[to]作为列名。
  2. 我硬编码了ID1和ID2而不是使用变量。
  3. 我并不担心“长度。”
  4. 你会看到它找到迂回路线,但不会让它们重复任何步骤。
  5. 未优化 - 仅显示其工作原理。
  6. 我在修改代码格式时遇到了一些麻烦。我会发布并尝试编辑。
  7. 底部的小提琴链接。
  8. CREATE TABLE路线(      ID int / identity / not null主键     ,启动char(1) - int     ,完成char(1) - int      - ,[length] int not null )

    GO
    
    INSERT INTO routes VALUES 
      (1,'a','b')
     ,(2,'a','c')
     ,(3,'a','d')
     ,(4,'b','c')
     ,(5,'b','d')
     ,(6,'c','d')
     ,(7,'d','c')
    
    GO
    
    WITH cte AS (
     --anchor
     SELECT id
           ,start
           ,finish
           ,',' + CAST(id AS VARCHAR(MAX)) + ',' route_ids
       FROM routes
      WHERE start = 'a'
    
      UNION ALL
     --recursive part    
     SELECT a.id
           ,a.start
           ,b.finish
           ,route_ids + CAST(b.id AS VARCHAR(MAX)) + ','
       FROM cte a
            INNER JOIN
            routes b ON a.finish = b.start 
      WHERE CHARINDEX(',' + CAST(b.id AS VARCHAR(MAX)) + ',',a.route_ids,1)  = 0
    )
    SELECT start,finish,route_ids 
     FROM cte
    WHERE finish = 'c'
    ORDER BY LEN(route_ids)
    

    Fiddle