PostgreSQL 递归 CTE - Return 如果找到错误值则为空

PostgreSQL Recursive CTE - Return Empty if false value found

使用递归查询,我正在使用 parent id 字段查询字段的所有祖先。如果在任何祖先的 enabled 字段中找到 false 值,则查询应 return 空行。

假设我有以下 table 称为 my_table

Field Type
id integer
parent integer
enabled boolean

它填充了以下数据:

id parent enabled
1 null true
2 1 true
3 1 true
4 2 true

我有以下递归查询:

WITH recursive my_rec AS
(
    SELECT id, parent, enabled
    FROM my_table
    WHERE id = 4
    
    UNION ALL

    SELECT t.id, t.parent, t.enabled
    FROM my_table t
    INNER JOIN my_rec
    ON t.id = my_rec.parent
)

SELECT *
FROM my_rec

对于 id = 4 这正确 returns

id parent enabled
4 2 true
2 1 true
1 null true

但是假设我要更新 id 2 以便它从 enabled true 更改为 false。 示例:

id parent enabled
1 null true
2 1 false
3 1 true
4 2 true

现在我希望我的查询 return 没有 id = 4。这是因为在 id 4 的“祖先”树中,enabledfalse for id 2.

如何更新上面的查询以实现此目的?

如果我没理解错你可以尝试使用NOT EXISTS子查询来 judge cte if any enabled is false 没有像你期望的那样显示任何东西,否则全部显示。

WITH recursive my_rec AS
(
    SELECT id, parent, enabled
    FROM my_table
    WHERE id = 4
    UNION ALL
    SELECT t.id, t.parent, t.enabled
    FROM my_table t
    INNER JOIN my_rec
    ON t.id = my_rec.parent
)
SELECT *
FROM my_rec
WHERE NOT EXISTS (
   SELECT 1
   FROM my_rec
   WHERE enabled = false
)

或者我们可以用COUNT条件聚合函数来做,得到false_cnt和判断

WITH recursive my_rec AS
(
    SELECT id, parent, enabled
    FROM my_table
    WHERE id = 4
    UNION ALL
    SELECT t.id, t.parent, t.enabled
    FROM my_table t
    INNER JOIN my_rec
    ON t.id = my_rec.parent
)
SELECT *
FROM (
 SELECT *,COUNT(*) FILTER(WHERE enabled = false) OVER() false_cnt
 FROM my_rec
) t1
WHERE false_cnt = 0

sqlfiddle