SQL按分级Code字段分组生成树形结构,还是在JS中处理更合适?
问题解答
是否可以通过SQL直接生成目标嵌套JSON
可以实现,但高度依赖你使用的数据库类型:
当前主流支持递归CTE和JSON函数的数据库(PostgreSQL、MySQL 8.0+、Oracle 12c+等)都能完成这个需求,核心实现思路如下:
- 第一步用递归CTE匹配每个节点的父节点:父节点Code为当前节点Code截掉最后1位,比如
011的父节点为01,根节点(长度为1的Code)无父节点 - 第二步通过数据库自带的JSON聚合函数(比如PostgreSQL的
json_agg、MySQL的JSON_ARRAYAGG)递归拼接嵌套结构,最后输出整棵树的JSON
但SQL实现存在非常明显的短板:
- 语法和数据库强绑定,换库就要完全重写
- 层级不固定、深度较深的场景,SQL编写和调试难度非常高
- 数据量大时递归查询性能远低于应用层遍历处理
更推荐的方案:JS(应用层)处理
绝大多数场景下把树形结构构造逻辑放在应用层用JS处理是更好的选择,实现简单、灵活好维护,示例代码如下:
function buildTree(data) { // 先把所有节点转成map,方便快速查找 const nodeMap = {} const rootNodes = [] data.forEach(item => { nodeMap[item.Code] = { ...item, children: [] } }) // 遍历所有节点,挂载到对应的父节点下 data.forEach(item => { const currentNode = nodeMap[item.Code] const parentCode = item.Code.slice(0, -1) // 没有父节点就是根节点 if (!parentCode || !nodeMap[parentCode]) { rootNodes.push(currentNode) } else { nodeMap[parentCode].children.push(currentNode) } }) return rootNodes } // 测试用,从数据库查询到的扁平数据 const flatData = [ { Name: 'John', Code: '0' }, { Name: 'Sam', Code: '01' }, { Name: 'Jack', Code: '011' }, { Name: 'Bill', Code: '02' }, { Name: 'Parent', Code: '1' }, { Name: 'Some1', Code: '11' }, { Name: 'Some2', Code: '111' }, { Name: 'Some3', Code: '112' }, { Name: 'Some4', Code: '1111' } ] console.log(buildTree(flatData))
这个实现不管层级多深都能正常生成嵌套结构,代码可读性高,调试和修改逻辑都非常方便,还和数据库选型完全解耦。
内容的提问来源于stack exchange,提问作者AlT
相关产品推荐
相关产品推荐

