【问题标题】:T-SQL Recursion; Multiple Recursions?T-SQL 递归;多重递归?
【发布时间】:2011-11-09 11:15:44
【问题描述】:

我正在尝试对递归问题的解决方案进行概念化,但我无法完全理解它。我有三张桌子。我们称它们为DocGroupGroupGroupGroupUser。在DocGroup 表中,有一条记录的分层结构,它将另一条记录指定为其父级,依此类推,直到一条记录成为它自己的父级。

Doc Group
1   1
2   2
3   2
4   3
5   2
6   4

GroupGroup 包含组嵌套:

Group    MemberGroup
4        2
4        1

GroupUser 将一个组映射到多个用户:

Group    User   Key
1        1      ABC
1        3      BCD
1        4      CDE
2        1      DEF
2        2      EFG
2        3      FGH
3        3      GHI
4        2      HIJ
4        3      IJK
4        4      JKL

所以我想指定一个用户和一个文档,并获取该组合的所有键的列表。例如,如果我选择用户 2 和文档 2,我需要返回“EFG”,但如果我选择文档 6 和用户 3,我需要返回“IJK”、“GHI”、“FGH”和“BCD”,因为组 2 和1 在第 4 组中,第 4 组 = 文档 4,其中有一组 3。在所有情况下,我只需要获取指定用户的记录。

我想我需要多次递归才能完成这项工作,但我似乎无法在脑海中描绘出如何在 SQL 中完成这项工作,我不想降级为循环和游标来执行此操作。

【问题讨论】:

  • 你为什么这么说group 4 = document 4
  • @ypercube,因为在第一个表中有一个层次结构,并且Group 在所有情况下都引用了Document,但并非所有Documents 在@987654334 的另一条记录中都指定了一个子级@字段。
  • 如果是这样,并且所有文档也是组,为什么需要2个层次结构?从第一个表中删除 Group 列并将这些关系 Doc - Group 添加到第二个表中。
  • 嗯,再想一想,这种设计是有道理的(在非常复杂的场景中)。我将调用Doc-Group 嵌套“绿色嵌套”和Group-MemebrGroup 一个“红色嵌套”。我猜你想要的是对于给定的用户,找到所有相关的组(使用第三个表)。然后,使用“红色”嵌套,找到这些相关组的所有父(和父-父等)组。然后使用“绿色”嵌套,找到这些父组的所有子(和孙子等)。因此,要从用户组转到文档,您使用红色和绿色路径,但红色仅向上走,绿色仅向下走。对吗?
  • 为了“简化管理” 既然您已经有了一个文档层次结构(其中一些是组),为什么还需要第二个层次结构?

标签: sql sql-server sql-server-2008 recursion recursive-query


【解决方案1】:

好的,答案如下:

DECLARE @Key varchar(max)

;WITH DocBase AS (
    SELECT Doc, Group
        FROM DocGroup
        WHERE Doc = @Doc
    UNION ALL
    SELECT DocGroup.Doc, DocGroup.Group
        FROM DocGroup INNER JOIN DocBase
            ON DocGroup.Doc = DocBase.Group
        WHERE DocBase.Doc <> DocBase.Group --to prevent infinite recursion
    ), GroupNesting AS (
    SELECT Doc
        FROM DocBase
    UNION ALL
    SELECT MemberGroup
        FROM GroupGroup.Group = GroupNesting.Doc
    ), GroupList AS (
    SELECT DISTINCT Doc
        FROM GroupNesting
    ), KeyList AS (
    SELECT Key
        FROM GroupList INNER JOIN GroupUser
            ON GroupList.Doc = GroupUser.Group
        WHERE User = @User
    )
SELECT @Key = COALESE(@Key, '') + Key
    FROM Key

SELECT @Key

我本可以使用http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/ 的任何建议来进行最终连接,但我选择了这种方法,因为它是最简单的,而且我还是要把它放在一个过程中。

【讨论】:

    【解决方案2】:

    我必须发布这个,因为我是一个狂暴的自大狂:

    The Zen of Recursion

    但是说真的,这就是我们过去的做法。这些天来,你会使用Common Table Expression

    HTH。

    【讨论】:

    • 我以前用过 CTE,我确信我必须用它们来解决这个问题,但是怎么做呢?顺便说一句,那篇文章看起来很有趣。
    猜你喜欢
    • 1970-01-01
    • 2014-04-18
    • 2018-11-27
    • 2014-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    相关资源
    最近更新 更多