【问题标题】:CTE for all Child for Multiple parent多父母的所有孩子的 CTE
【发布时间】:2016-08-25 06:03:52
【问题描述】:

我有一个父子关系表如下图:

ContractID        ContractIdRef
----------        -------------
 1                 null
 2                 1
 3                 1
 4                 2
 5                 4
 10                null
 11                10
 12                11
 15                null
 16                12

我想要如下结果:

 ContractID        ContractIdRef    rw
-----------        --------------   ---
 1                 null             1
 2                 1                1
 3                 1                1
 4                 2                1
 5                 4                1
 10                null             10
 11                10               10
 12                11               10
 15                null             15
 16                12               10

在上面的结果中,我想指定每一行的父级。
谢谢

【问题讨论】:

    标签: sql recursion common-table-expression


    【解决方案1】:

    正如你在标签中提到的那样,Comman Table Expression 是要走的路

    ;WITH REC_CTE 
         AS (SELECT [contractid], 
                    [ContractIdRef], 
                    [contractid] AS rw
             FROM   Yourtable
             WHERE  [contractidref] IS NULL 
             UNION ALL 
             SELECT T.[contractid], 
                    T.[contractidref], 
                    c.rw
             FROM   Yourtable AS T 
                    INNER JOIN REC_CTE C 
                            ON T.[contractidref] = c.[contractid] 
             WHERE  T.[contractid] <> T.[contractidref]) 
    SELECT [contractid], 
           [contractidref],
           rw
    FROM   REC_CTE 
    ORDER  BY [contractid] 
    

    演示

    架构设置

    If object_id('tempdb.dbo.#Yourtable') is not null
    DROP table #Yourtable
    
    CREATE TABLE #Yourtable
        ([ContractID] INT, [ContractIdRef] INT);
    

    样本数据

    INSERT INTO #Yourtable
        ([ContractID], [ContractIdRef])
    VALUES
        ('1', NULL),
        ('2', '1'),
        ('3', '1'),
        ('4', '2'),
        ('5', '4'),
        ('10', NULL),
        ('11', '10'),
        ('12', '11'),
        ('15', NULL),
        ('16', '12');
    

    查询

    ;WITH REC_CTE
         AS (SELECT [ContractID], 
                    [ContractIdRef] as [ContractIdRef],
                    [ContractID] AS rw 
             FROM   #Yourtable where [ContractIdRef] is null
    
             UNION ALL 
             SELECT T.[ContractID], 
                    T.[ContractIdRef], 
                    c.rw 
             FROM   #Yourtable  AS T 
                    INNER JOIN REC_CTE c 
                            ON T.[ContractIdRef] = c.[ContractID] 
             WHERE  T.[ContractID] <> T.[ContractIdRef]) 
    SELECT [ContractID], 
           [ContractIdRef],
           rw 
    FROM   REC_CTE 
    ORDER  BY [ContractID]  
    

    结果

    +-----------+-------------+----+
    |ContractID |ContractIdRef| rw |
    +-----------+-------------+----+
    |1          |NULL         | 1  |
    |2          |1            | 1  |
    |3          |1            | 1  |
    |4          |2            | 1  |
    |5          |4            | 1  |
    |10         |NULL         | 10 |
    |11         |10           | 10 |
    |12         |11           | 10 |
    |15         |NULL         | 15 |
    |16         |12           | 10 |
    +-----------+-------------+----+    
    

    【讨论】:

      【解决方案2】:
      with Q as(
        select ContractID, ContractIdRef, ContractID as root
          from childs
         where ContractIdRef is null
       union all
        select C.ContractID, C.ContractIdRef, Q.root
          from Q, childs C
         where C.ContractIdRef=Q.ContractID
      )
      select * from Q
       order by ContractID
      

      在 MS SQL 2014 上测试。

      对于 Postgresql 需要在 'with' 之后添加单词 'recursive'。 Test on sqlfiddle.com

      对于 Oracle,第一行写成with Q(ContractID,ContractIdRef,root)

      【讨论】:

        猜你喜欢
        • 2013-11-23
        • 2021-07-04
        • 1970-01-01
        • 2018-01-29
        • 2015-03-26
        • 1970-01-01
        • 2021-08-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多