【问题标题】:SQL Database Parent/Child recursionSQL 数据库父/子递归
【发布时间】:2013-12-24 08:48:51
【问题描述】:

这是我的桌子:

parent_id | child_id
--------------
        1 | 2
        1 | 3
        1 | 4
        2 | 5
        2 | 6
        5 | 8
        8 | 9
        9 | 5

我需要获取父 2 下的所有项目。我发现了一些与此类似的东西,但不知道如何使它适用于我的情况。我不断收到maximum recursion 限制。这是我所拥有的:

WITH CTE AS
(
    SELECT gt.[child_id]
      FROM [CHSPortal].[dbo].[company_adgroupstoadgroups] gt
     WHERE gt.parent_id='2'

    UNION ALL

    SELECT g.[child_id]
      FROM [CHSPortal].[dbo].[company_adgroupstoadgroups] g
      INNER JOIN CTE g2 on g.parent_id=g2.child_id
)
select distinct child_id from CTE

期望的结果将是:2,3,4,5,6,8,9。

我需要进行哪些修改才能获得子2 下所有项目的列表。我也希望2(父节点)出现在列表中。任何帮助将不胜感激。

【问题讨论】:

  • 我想知道样本数据是不是真实数据?因为据此,您将实现无限递归。 2 下的所有项目 = 5,6。 5以下= 8,8以下= 9, 9以下= 5,然后无限期回到5,8,9。
  • 为什么不只使用一个 select 语句并使用 where 子句: where parent_id = 2?您还说您需要父母 2 下的所有项目,然后您需要孩子 2 下的所有项目。你在找什么?
  • @the_pete - 表中的数据表示“树”或其他递归结构,OP 正在寻找 Tree Traversal。当然,这个特定的例子有明显的周期性数据问题。一个简单的SELECT 语句不足以完成此任务 - 此类工作需要特定的语法,因为现有答案正在使用。
  • 我会无限循环,但因为这是数据结构的设置方式。但它不会继续添加节点。一旦它回到以前的值,我就不需要它更深了。

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


【解决方案1】:

首先,您的示例中有一个循环 (5|8, 8|9, 9|5),这就是您达到最大递归限制的原因。

关于过滤问题,下面是一个根节点过滤的例子:

;WITH MTree (parent_id, child_id, LEVEL) AS (
    SELECT t.parent_id , t.child_id, 0 AS LEVEL 
    FROM table_1 t
    WHERE child_id = 2 --here you can filter the root node
UNION ALL      
    SELECT m.parent_id , m.child_id, LEVEL + 1
    FROM Table_1 m
        INNER JOIN MTree t ON t.child_id = m.parent_id
)

SELECT * FROM Mtree;

【讨论】:

  • 如果您想排除相应的顶行,请在 CTE 中使用以下过滤器:WHERE parent_id = 2 --here you can filter the root node
【解决方案2】:

除了与您提供的示例数据无关之外,不确定您的查询有什么问题,但这很好用:

;WITH src AS (SELECT 1 AS parent_id, 2 AS child_id
               UNION  SELECT 1, 3
               UNION  SELECT 1, 4
               UNION  SELECT 2, 5
               UNION  SELECT 2, 6
               UNION  SELECT 5, 8
               UNION  SELECT 8, 9
               UNION  SELECT 9, 5)
    ,cte AS (SELECT *
             FROM src
             WHERE child_id = 2
             UNION  ALL
             SELECT a.*
             FROM src a
             JOIN cte b
               ON a.parent_id = b.child_id           
            )
SELECT TOP 100 *
FROM cte

--由于样本数据的无限递归问题,限制在前100名。

【讨论】:

  • 限制确实可以防止无限递归问题,但实际数据远大于100个实体,我不希望重复。如何在不知道将返回多少数据的情况下获得不同的值列表?
  • 您可以使用OPTION (MAXRECURSION 0) 设置最大递归因子,将0 调整为有意义的数字,然后将DISTINCT 添加到SELECT 语句中。但是,您的数据才是真正的问题,您可以添加一个防止无限循环的WHERE 子句。
猜你喜欢
  • 2014-10-24
  • 1970-01-01
  • 2014-05-19
  • 1970-01-01
  • 2014-06-02
  • 2017-11-10
  • 2021-11-02
  • 2020-07-23
  • 2010-10-03
相关资源
最近更新 更多