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

子节点数量不同的表用UNION遇问题,求SQL解决方案

解决递归CTE查询层级表时的列数不匹配问题

看起来你在尝试用递归CTE遍历层级结构的Categories表时踩了两个小坑,导致出现了UNION ALL操作目标列数不一致的错误,我来帮你梳理并解决这个问题:

先看你SQL里的两个明显问题:

  1. 别名拼写错误:递归部分里写了rr.parentId,但你定义的子节点表别名是cc,这里完全没定义rr,属于笔误;
  2. 列数不匹配:锚点查询是select * from Categories c where c.parentId = -1,返回的是3列(id、Name、parentId),但递归查询里你用了select * from Categories cc inner join testtable tt on ...,JOIN之后会返回Categories的3列 + testtable的3列,总共6列,和锚点的列数完全不一致,这就是报错的核心原因。

修正后的正确递归CTE写法:

递归CTE要求锚点成员和递归成员返回完全相同数量、相同类型的列,所以我们要明确指定要返回的列,避免用*带来的列数变化:

WITH testtable AS (
    -- 锚点成员:获取所有根节点(parentId = -1)
    SELECT id, Name, parentId
    FROM Categories
    WHERE parentId = -1
    UNION ALL
    -- 递归成员:逐层获取子节点,关联CTE中的父节点
    SELECT c.id, c.Name, c.parentId
    FROM Categories c
    INNER JOIN testtable tt ON tt.id = c.parentId
)
SELECT * FROM testtable;

额外扩展:如果需要展示层级路径

如果你想直观看到每个节点的层级路径,可以给CTE添加一个path列,方便查看节点的归属关系:

WITH testtable AS (
    SELECT 
        id, 
        Name, 
        parentId, 
        CAST(Name AS VARCHAR(MAX)) AS node_path  -- 根节点路径就是自身名称
    FROM Categories
    WHERE parentId = -1
    UNION ALL
    SELECT 
        c.id, 
        c.Name, 
        c.parentId, 
        CONCAT(tt.node_path, ' > ', c.Name) AS node_path  -- 拼接父路径和当前节点名称
    FROM Categories c
    INNER JOIN testtable tt ON tt.id = c.parentId
)
SELECT * FROM testtable;

总结一下错误根源:

递归CTE的UNION ALL两边必须保证列数、列顺序、列类型完全一致,你原来的写法因为JOIN了CTE表导致列数翻倍,触发了SQL的语法检查错误。只要明确指定要返回的列,同时修正别名笔误,就能顺利遍历整个层级结构啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:55:31