在具有附加条件的树中查找实体的后代 (PostgreSQL)

Finding entity's descendants in a tree with an additional condition (PostgreSQL)

我有一个名为类别的实体,每个类别都可以有任意数量的子类别。如果我知道一个类别 ID,我可以通过以下方式追踪它的所有后代:

WITH RECURSIVE subcategories AS (
    select id, is_locked_by
    FROM category
    WHERE id = categoryId
    UNION
    SELECT c.id, c.is_locked_by
    FROM category c
    INNER JOIN subcategories subs on subs.id = c."parentCategoryId"
) 
SELECT id FROM subcategories;

每个类别都有两个参数:is_locked_byis_lockedis_locked_by 参数表示锁定类别。例如,如果我有一个 id = 10 且其 is_locked_by = 5 的类别,则意味着 id = 10 的类别被 id = 5 的类别锁定。从技术上讲,这意味着 id 的类别= 5 被密码锁定,它包含 ID 为 10 的类别。 is_locked参数表示类别本身被锁定,即直接在该类别上设置密码。

----19---
    |
    25
    |
26* | 27 | 28
|
29

这是类别树,应该这样理解:类别19是顶级类别,它包含类别25,其中包含类别26、27和28,类别26包含第29个类别,id = 26 被锁定(用 * 表示)。

给定 categoryId = 19,结果应该是 19、25、27 和 28。给定 categoryId = 25,结果应该是 25、27 和 28。换句话说,我想找到 is_locked = false 的所有后代,这些后代未被 is_locked = true 的那些类别锁定。 我该如何编写这样的查询?

希望我说得够清楚....

您想忽略锁定的类别及其子项。您可以在递归成员的 WHERE 子句中将它们过滤掉:

WITH RECURSIVE subcategories AS (
    select id, is_locked_by
    FROM category
    WHERE id = ?
    UNION ALL
    SELECT c.id, c.is_locked_by
    FROM category c
    INNER JOIN subcategories subs on subs.id = c."parentCategoryId"
    WHERE c.is_locked IS NULL
    ) 
SELECT id FROM subcategories;

根据 is_locked 列的数据类型和值,WHERE 谓词可能略有不同。例如,如果它是布尔值:

WHERE NOT c.is_locked