To find infinite recursive loop in CTE

后端 未结 6 387
梦如初夏
梦如初夏 2020-12-16 00:55

I\'m not a SQL expert, but if anybody can help me.

I use a recursive CTE to get the values as below.

Child1 --> Parent 1

Parent1 --> Parent 2

6条回答
  •  臣服心动
    2020-12-16 01:24

    Here's an alternate method for detecting cycles in adjacency lists (parent/child relationships) where nodes can only have one parent which can be enforced with a unique constraint on the child column (id in the table below). This works by computing the closure table for the adjacency list via a recursive query. It starts by adding every node to the closure table as its own ancestor at level 0 then iteratively walks the adjacency list to expand the closure table. Cycles are detected when a new record's child and ancestor are the same at any level other than the original level zero (0):

    -- For PostgreSQL and MySQL 8 use the Recursive key word in the CTE code:
    -- with RECURSIVE cte(ancestor, child, lev, cycle) as (
    
    with cte(ancestor, child, lev, cycle) as (
      select id, id, 0, 0 from Table1
      union all
      select cte.ancestor
           , Table1.id
           , case when cte.ancestor = Table1.id then 0 else cte.lev + 1 end
           , case when cte.ancestor = Table1.id then cte.lev + 1 else 0 end
        from Table1
        join cte
          on cte.child = Table1.PARENT_ID
       where cte.cycle = 0
    ) -- In oracle uncomment the next line
    -- cycle child set isCycle to 'Y' default 'N'
    select distinct
           ancestor
         , child
         , lev
         , max(cycle) over (partition by ancestor) cycle
      from cte
    

    Given the following adjacency list for Table1:

    | parent_id | id |
    |-----------|----|
    |    (null) |  1 |
    |    (null) |  2 |
    |         1 |  3 |
    |         3 |  4 |
    |         1 |  5 |
    |         2 |  6 |
    |         6 |  7 |
    |         7 |  8 |
    |         9 | 10 |
    |        10 | 11 |
    |        11 |  9 |
    

    The above query which works on SQL Sever (and Oracle, PostgreSQL and MySQL 8 when modified as directed) rightly detects that nodes 9, 10, and 11 participate in a cycle of length 3.

    SQL(/DB) Fiddles demonstrating this in various DBs can be found below:

    • Oracle 11gR2
    • SQL Server 2017
    • PostgeSQL 9.5
    • MySQL 8

提交回复
热议问题