WITH RECURSIVE SELECT 通过辅助 table

WITH RECURSIVE SELECT via secondary table

我很难把它拼凑起来。我不擅长数据库或复杂的查询。

数据库

我正在使用最新的 MariaDB 版本。

我有一个数据库table这样的配置,代表一个分层数据结构:

|----------------------|
| fieldsets            |
|----+-----------------|
| id | parent_field_id |
|----+-----------------|
| 1  | NULL            |
| 2  | 1               |
|----------------------|

|-------------------------|
| fields                  |
|----+--------------------|
| id | parent_fieldset_id |
|----+--------------------|
| 1  | 1                  |
| 2  | 1                  |
|-------------------------|

问题

我正在尝试拼凑一个递归查询。我需要 select 给定层次结构中的每个字段集。例如,在上面的 stripped-down 示例中,我想要 select fieldset of id = 1,以及每个后代 fieldset.

层次结构中任何给定级别的下一个梯级的 ID 只能通过次级 table 的列获得。

table fieldsets 不包含我可以直接获取所有 child fieldsets 的列。我需要获取给定 fieldset 的 child 的所有 fields,然后获取 field 的 child 的所有 fieldsets ].

更好地说明问题

由于报告的错误,此查询无效:"Restrictions imposed on recursive definitions are violated for table all_fieldsets"

但是,它确实说明了我需要做什么才能获得层次结构中的所有后代 fieldsets(请记住,字段集不包含其 parent [=19= 的列) ],因为 fieldset 不能将 fieldset 作为直接 parent。相反,fieldset 有一个 parent_field_id,它指向 [= 中的一行18=] table,fields table 中的那一行相应地有一个名为 parent_fieldset_id 的列,它指向 fieldsets [=80] 中的一行=],这被认为是 parent fieldsetfieldset,只是一个间接的 parent.

WITH RECURSIVE all_fieldsets AS (
    SELECT fieldsets.* FROM fieldsets WHERE id = 125
    UNION ALL
    SELECT fieldsets.* FROM fieldsets
    WHERE fieldsets.parent_field_id IN (
        SELECT id FROM fields f
        INNER JOIN all_fieldsets afs
        WHERE f.parent_fieldset_id = afs.id
    )
)
SELECT * FROM all_fieldsets

我的尝试

到目前为止我的查询(不起作用):

WITH RECURSIVE all_fieldsets AS (
    SELECT fieldsets.* FROM fieldsets WHERE id = 125
    UNION
    SELECT fieldsets.* FROM fieldsets WHERE fieldsets.id IN (SELECT fs.id FROM fieldsets fs LEFT JOIN fields f ON f.id = fs.parent_field_id WHERE f.parent_fieldset_id = fieldsets.id)
)
SELECT * FROM all_fieldsets

我的研究

我也很难找到适合我 use-case 的示例。对于涉及一个 table 仅与自身有关系的层次结构,有很多结果,而不是像我的情况那样通过辅助 table。当您不知道某些概念的正确术语时,这很困难,而且任何外行解释似乎都会产生太多切线搜索结果。

我的请求

我将非常感谢所有能指出我出错的地方,并可能提出可行的查询大纲的人。

我在您当前的代码中看到的主要问题是 CTE 的递归部分(出现在并集之后的查询)没有从递归 CTE 中选择,而它应该是。考虑这个更新版本:

WITH RECURSIVE all_fieldsets AS (
    SELECT * FROM fieldsets WHERE id = 125
    UNION ALL
    SELECT f1.*
    FROM fieldsets f1
    INNER JOIN all_fieldsets f2
        ON f1.parent_field_id = f2.id
)

SELECT *
FROM all_fieldsets;

请注意,CTE 的递归部分中的联接将 fieldsets 中的给定后代记录与其在 CTE 中的父项相关联。

我下班回到家,我就是无法放下它!

但是,从中得出了一个解决方案。

我强烈建议阅读这个关于递归查询的答案,以更好地了解它们的工作原理以及语法的含义。非常精彩的解释:How to select using WITH RECURSIVE clause

解决方案

WITH RECURSIVE all_fieldsets AS (
    SELECT * FROM fieldsets fs
        WHERE id = 59
    UNION ALL
    SELECT fs.* FROM fieldsets fs
        INNER JOIN all_fieldsets afs
        INNER JOIN fields f
            ON f.parent_fieldset_id = afs.id
            AND fs.parent_field_id = f.id
)
SELECT * FROM all_fieldsets

我不得不使用连接从 fields table 中获取信息,以便获得层次结构中的下一级,然后递归执行此操作,直到结果为空递归查询。