开发递归/层次结构查询

时间:2012-11-27 21:49:48

标签: sql sql-server

我需要你的帮助,我无法解决这个问题。 这就是问题,假设我有一张这样的表:

Father | Son
1      |   2
1      |   3
1      |   4
3      |   5
3      |   6
2      |   7
4      |   8
5      |   9
6      |   10

因为你可以看到这个表代表父子关系,我需要找到一个父亲的所有儿子(和儿子的儿子),例如,如果我正在寻找1号的儿子,我们将得到像这样的表

Father | son
1      |   2
1      |   3
1      |   4
1      |   5
1      |   6
1      |   7
1      |   8
1      |   9
1      |   10

如果我为第3号的儿子们取笑,我们会得到:

Father | son
3      |   5
3      |   6
3      |   9
3      |   10
好吧,我认为你理解我的观点。接下来的问题是我必须为表中的每个父亲做这件事。所以最后,表格如下:

Father | son
1      |   2
1      |   3
1      |   4
1      |   5
1      |   6
1      |   7
1      |   8
1      |   9
1      |   10
3      |   5
3      |   6
3      |   9
3      |   10
2      |   7
4      |   8
5      |   9
6      |   10

非常类似于过树。 我一直试图找出这个查询一段时间但没有成功。我做了像这样的代码

WITH  son
        AS (
              -- in 
            SELECT  FK_CC_B
            FROM    PG_Rols_CC  
            WHERE   FK_CC_A = @idCC
            UNION ALL
              --recur
            SELECT  t.FK_CC_B
            FROM     PG_Rols_CC AS t
                    JOIN hijos AS a
                      ON t.FK_CC_A = a.FK_CC_B
           )
insert into @TableSons (idSon) SELECT * FROM son

但它并不适用于每个父亲同时生成的表格略有不同,它只有儿子ID。示例

son
3
4
5
6
7

希望你能帮助我。

2 个答案:

答案 0 :(得分:4)

如果你想得到所有父亲的后代,你需要摆脱公用表格表达式(CTE)第一部分的WHERE条款。

如果要输出两列(父和后代),则需要将这些列添加到CTE的两个部分。

像这样:

WITH Son
AS
(
    SELECT
        FK_CC_A AS Father,
        FK_CC_B AS Son
    FROM
        PG_Rols_CC
    UNION ALL
    SELECT
        f.Father,
        s.FK_CC_B AS Son
    FROM
        Son f
        INNER JOIN PG_Rols_CC s ON f.Son = s.FK_CC_A
)

SELECT * FROM Son

答案 1 :(得分:3)

你需要从'递归'成员中引用'Anchor'部分......

这样的事情是否有效:

WITH  son
        AS (
              -- in 
            SELECT  @Father, Son
            FROM    PG_Rols_CC  
            WHERE   FK_CC_A = @Father
            UNION ALL
              --recur
            SELECT  @Father, Son
            FROM     PG_Rols_CC AS t
                    JOIN son AS s
                      ON s.FK_CC_A = t.FK_CC_B
           )
SELECT * FROM son