You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL递归查询:满足条件时立即终止递归

递归遍历层级表:找到首个非空rule行后终止

场景与数据

现有层级结构表product_categories,数据如下:

select * from product_categories;
 id | parent_id |     item     |     rule
----+-----------+--------------+---------------
  1 |           | ecomm        |
  2 |         1 | grocceries   |
  3 |         1 | electronics  |
  5 |         3 | TV           |
  6 |         4 | touch_screen | Rules applied
  7 |         4 | qwerty       |
  8 |         6 | iphone       |
  4 |         3 | mobile       | mobile rules

需求

从item为'iphone'的节点向上遍历层级,一旦遇到rule列非空的行,就返回该行并立即终止递归,不再继续向上查找父节点。

原查询及问题

原查询代码:

WITH RECURSIVE items AS (
        SELECT id, item, parent_id, rule
        FROM product_categories
        WHERE item = 'iphone'
    UNION ALL
        SELECT p.id, p.item, p.parent_id, p.rule
        FROM product_categories p
        JOIN items ON p.id = items.parent_id
        WHERE p.rule is not NULL
)
SELECT * FROM items ;

查询结果:

id |     item     | parent_id |     rule
----+--------------+-----------+---------------
  8 | iphone       |         6 |
  6 | touch_screen |         4 | Rules applied
  4 | mobile       |         3 | mobile rules

原查询的问题是:会返回所有符合rule非空的父节点,无法在找到第一个匹配行后终止递归。

修改后的查询方案

方法一:通过递归条件直接控制终止

WITH RECURSIVE items AS (
    SELECT id, item, parent_id, rule
    FROM product_categories
    WHERE item = 'iphone'
    UNION ALL
    SELECT p.id, p.item, p.parent_id, p.rule
    FROM product_categories p
    JOIN items ON p.id = items.parent_id
    WHERE items.rule IS NULL  -- 仅当前节点无rule时,才继续向上遍历父节点
)
SELECT id, item, parent_id, rule
FROM items
WHERE rule IS NOT NULL
LIMIT 1;

方法二:增加深度标记确保取首个匹配行(更严谨)

如果担心递归顺序不确定,可以添加深度字段明确遍历顺序:

WITH RECURSIVE items AS (
    SELECT id, item, parent_id, rule, 1 AS depth
    FROM product_categories
    WHERE item = 'iphone'
    UNION ALL
    SELECT p.id, p.item, p.parent_id, p.rule, items.depth + 1 AS depth
    FROM product_categories p
    JOIN items ON p.id = items.parent_id
    WHERE items.rule IS NULL
)
SELECT id, item, parent_id, rule
FROM items
WHERE rule IS NOT NULL
ORDER BY depth ASC
LIMIT 1;

结果说明

执行修改后的查询,会返回首个匹配的行:

id |     item     | parent_id |     rule
----+--------------+-----------+---------------
  6 | touch_screen |         4 | Rules applied

核心逻辑

  1. items.rule IS NULL作为递归连接的条件:确保只有当前递归到的节点没有非空rule时,才会继续向上查找父节点。一旦找到有非空rule的节点,后续递归就会停止。
  2. 最后筛选出rule非空的行,并取第一行(或按深度从小到大取第一行),得到需要的首个符合条件的节点。

内容的提问来源于stack exchange,提问作者Rahul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:37:06