获取针对特定子项的父记录或针对父项获取子记录的查询是啥?

Posted

技术标签:

【中文标题】获取针对特定子项的父记录或针对父项获取子记录的查询是啥?【英文标题】:What is the query to get parent records against specific child or get child records against parent?获取针对特定子项的父记录或针对父项获取子记录的查询是什么? 【发布时间】:2017-09-06 22:35:56 【问题描述】:

场景:

我的表中有以下层次结构格式的数据:

PERSON_ID   Name    PARENT_ID
1           Azeem   1
2           Farooq  2
3           Ahsan   3
4           Waqas   1
5           Adnan   1
6           Talha   2
7           Sami    2
8           Arshad  2
9           Hassan  8

例如

Hassan 是 parent_id 8 的孩子,即 (Arshad)

并且 Arshad 是 parent_id 2 的孩子,即 (Farooq)

我想要什么:

首先,我想找到特定 parent_id 的 parent 的所有 parent。

例如:如果我想找到 Hassan 的父级,那么我也得到 Hassan 的父级并得到它的父级 (Hassan -> Arshad -> Farooq)

其次,我想找到 Farooq 的所有孩子,例如 (Farooq -> Arshad -> Hassan)

第三,如果 Azeem 也有像 (Azeem -> Azeem) 一样的父级,那么给我看这条记录。

我已经尝试过的:

DECLARE @id INT
SET @id = 9

;WITH T AS (
    SELECT p.PERSON_ID,p.Name, p.PARENT_ID
        FROM hierarchy p
        WHERE p.PERSON_ID = @id AND p.PERSON_ID != p.PARENT_ID
    UNION ALL
    SELECT c.PERSON_ID,c.Name, c.PARENT_ID
        FROM hierarchy c
        JOIN T h ON h.PARENT_ID = c.PERSON_ID)
 SELECT h.PERSON_ID,h.Name FROM T h

它向我显示以下错误:

语句终止。在语句完成之前,最大递归 100 已用完。

【问题讨论】:

我删除了mysql 标签,因为我怀疑您使用的是 MySQL。看起来您使用的是 Microsoft SQL Server,所以我添加了该标签。 @BillKarwin 我很感激。 您的数据中有一个无限循环:Azeem 是他自己的父母。您需要将值设为NULL 或将您的条件更改为WHERE p.parent_id = @id AND p.parent_id != p.child_id 【参考方案1】:

如果我正确理解您的问题,即您不想在 Parent_ID 列中插入空值,那么您应该将 NULL 替换为 0 并且您的更新代码将如下所示:

;WITH DATA AS (
                SELECT p.PERSON_ID,p.Name, p.PARENT_ID
                FROM hierarchy p
                WHERE p.PERSON_ID = 9
                UNION ALL
                SELECT c.PERSON_ID,c.Name, c.PARENT_ID
                FROM hierarchy c
                JOIN DATA h 
                ON c.PERSON_ID = h.PARENT_ID 
          )
select * from DATA;

【讨论】:

【参考方案2】:

您的数据中有一个无限循环:Azeem 是他自己的父母。您需要将他的值设为NULL 或将您的条件更改为WHERE p.parent_id = @id AND p.parent_id != p.child_id

另外,我觉得你的列命名方式错误 - 主键应该命名为 person_id 而不是 parent_id 并且你命名为 child_id 的列实际上指向该人的 父母 em>,所以应该改成parent_id

【讨论】:

根据您的格式,我已经编辑了我的帖子,我还添加了一个条件,即如果 Azeem 是它自己的父级,那么也向我显示这条记录。如果我在 Parent_ID 列中输入 null 值,它会返回数据,但是当在参数 @id 中传递值 2 并且其 Parent_ID 为 null 时,它不会提供任何记录。但我想如果 Person_ID 和 Parent_ID 相同,那么它会显示记录。 为什么我的帖子被否决是我的问题中缺少的东西? 请看我的回答。【参考方案3】:

好吧,我为上述案例找到了一种方法:

如果我有以下表格结构:

PERSON_ID   Name    PARENT_ID
1           Azeem   NULL
2           Farooq  NULL
3           Ahsan   NULL
4           Waqas   1
5           Adnan   1
6           Talha   2
7           Sami    2
8           Arshad  2
9           Hassan  8

然后我尝试了以下查询,如果 Parent_ID 具有 NULL 值意味着该记录不再有父记录,则该查询工作正常。

DECLARE @id INT
SET @id = 2

Declare @Table table(
    PERSON_ID bigint,
    Name varchar(50),
    PARENT_ID bigint
    );

;WITH T AS (
SELECT p.PERSON_ID,p.Name, p.PARENT_ID
    FROM hierarchy p
    WHERE p.PERSON_ID = @id AND p.PERSON_ID != p.PARENT_ID
UNION ALL
SELECT c.PERSON_ID,c.Name, c.PARENT_ID
    FROM hierarchy c
    JOIN T h ON h.PARENT_ID = c.PERSON_ID)
insert into @table 
select * from T;

IF exists(select * from @table)
BEGIN
    select PERSON_ID,Name from @table
End
Else
Begin
    select PERSON_ID,Name from Hierarchy
    where PERSON_ID = @id
end

上面的查询显示我设置参数值@id = 1时的期望输出

上面的查询显示我设置参数值@id = 9时的期望输出

问题:

我不想在 Parent_ID 中插入空值,比如如果该 Person 没有更多的 Parent,那么我在 Parent_ID 列中插入相同的 Person_ID。 如果我用 person_id 替换空值,则会出现以下错误。

语句终止。在语句完成之前,最大递归 100 已用完。

【讨论】:

在查询末尾指定 maxrecursion 选项: ... from EmployeeTree option (maxrecursion 0) 这允许您指定 CTE 在生成错误之前可以递归的频率。 Maxrecursion 0 允许无限递归。 ***.com/questions/9650045/… @Brainsbot 我看到了这篇文章并在我的代码中应用了接受的答案,但这在我的场景中不起作用。除非我按下停止执行按钮来中断递归循环,否则循环不会停止它的持续运行。

以上是关于获取针对特定子项的父记录或针对父项获取子记录的查询是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Rails 4+ 最佳实践:删除父项同时保留子项

JPA - 如果已获取父项,则 JpaRepository 子记录具有父 ID 而不是实体记录 [重复]

获取特定子记录的 SQL 查询

如何将父项的第一个子项中的属性移动到 XSLT 中的父项?

如何在php中数组的父项下显示子项

如何设置子查询以获取具有最新日期和最大 ID 的单个记录?