如何用PostgreSQL递归SQL查询产品的顶级父分类ID
PostgreSQL递归查询获取顶级分类父ID的正确写法
你的递归查询有两个核心问题,导致只返回直接父ID:
- 递归分支没有继续向上查询父分类的
parent_id,只是重复输出当前的temp值,没有关联product_category表获取更上层的父级。 - 判断非空的方式错误:PostgreSQL中不能用
!= Null,必须用IS NOT NULL——因为NULL是未知值,和任何值比较结果都是NULL,不会返回true。
另外,初始查询应该先拿到产品对应的分类ID,再从该分类开始向上递归,逻辑更清晰,也能处理产品分类本身就是顶级的情况。
修正后的递归查询语句
WITH RECURSIVE category_ancestors AS ( -- 锚点成员:获取目标产品对应的分类ID,以及该分类的父ID SELECT pp.categ_id AS category_id, pc.parent_id AS parent_category_id FROM product_product pp JOIN product_category pc ON pp.categ_id = pc.id WHERE pp.product_id = 'ABC123' UNION ALL -- 递归成员:用当前分类的父ID,继续查询其父级的父ID SELECT pc.id AS category_id, pc.parent_id AS parent_category_id FROM category_ancestors ca JOIN product_category pc ON ca.parent_category_id = pc.id WHERE ca.parent_category_id IS NOT NULL ) -- 筛选出顶级父分类(parent_id为NULL的那条) SELECT category_id AS top_parent_id FROM category_ancestors WHERE parent_category_id IS NULL;
关于内连接的疑问解答
多数父子关联示例用内连接,原因是:
- 递归过程中,我们只需要存在父节点的分类才能继续向上追溯。内连接会自动过滤掉
parent_category_id为NULL的情况(因为没有对应的父分类记录),让递归自然终止。 - 如果用左连接,会把NULL值也带入递归分支,需要额外加判断条件才能终止递归,不仅代码冗余,还可能导致不必要的NULL值处理,效率更低。
内容的提问来源于stack exchange,提问作者Zprak
相关产品推荐
相关产品推荐

