SQL Server 2017如何快速计算树形结构表中所有叶子节点的数值总和
树形表叶子节点值高效求和方案
方案1:无需修改表结构的最优查询写法
核心逻辑:叶子节点的定义是不存在任何子节点,即没有其他行的parent_id等于当前行的id。
前置优化:给parent_id字段建立普通索引,这是查询高效的核心前提。
对应的查询语句如下:
SELECT SUM(val) AS leaf_total FROM test_1 t1 WHERE NOT EXISTS ( SELECT 1 FROM test_1 t2 WHERE t2.parent_id = t1.id );
该方案只要parent_id有索引,千万级数据量下也能在百毫秒级别返回结果,不需要遍历整棵树,也不需要递归计算层级,性能远高于递归CTE等遍历树的写法。
方案2:高频查询场景的预计算优化
如果这个求和是业务高频查询,或者表的树结构更新频率较低,可以新增标记字段进一步降低查询成本:
- 新增
is_leaftinyint类型字段,默认值为1,代表新增节点默认是叶子节点 - 业务侧在节点增删改时同步维护这个标记:
- 给某个节点新增子节点时,将该节点的
is_leaf更新为0 - 删除某个节点的最后一个子节点时,将该节点的
is_leaf更新为1
- 给某个节点新增子节点时,将该节点的
- 给
is_leaf建立索引后,求和查询可以简化为:
SELECT SUM(val) AS leaf_total FROM test_1 WHERE is_leaf = 1
这个方案的查询性能是最高的,仅需要一次索引扫描,几乎不受数据总量影响。
注意事项
- 不要使用递归CTE遍历树的方式计算叶子节点总和,递归方案在树层级深、数据量大的情况下性能会远低于上述两种方案
- 建议给
parent_id增加外键约束,避免出现无效的parent_id指向已删除节点的情况,导致叶子节点判断错误
内容的提问来源于stack exchange,提问作者filippo
相关产品推荐
相关产品推荐

