如何使用SQL查找余额加总等于指定金额的所有账户ID组合
解法说明
这个需求属于子集和匹配场景,需要用递归CTE遍历所有合法的行组合实现,正确SQL如下:
WITH RECURSIVE subset_sum AS ( -- 锚点:单个行作为初始组合 SELECT ARRAY[id] AS id_combination, balance AS total_balance, id AS current_max_id FROM accountbalances WHERE balance <= 5778.1 -- 剪枝:单条金额超过目标直接排除 UNION ALL -- 递归:拼接id更大的行,避免重复生成相同组合 SELECT ss.id_combination || ab.id, ss.total_balance + ab.balance, ab.id FROM subset_sum ss INNER JOIN accountbalances ab ON ab.id > ss.current_max_id WHERE ss.total_balance + ab.balance <= 5778.1 -- 剪枝:总和超目标停止扩展 ) -- 筛选符合目标的组合 SELECT id_combination, total_balance FROM subset_sum WHERE abs(total_balance - 5778.1) < 0.0001; -- 兼容浮点数精度误差
你提供的样例数据中,不含0值的符合条件组合为{5,10,11,12,14,17},叠加id7、id8的0值余额,共会输出4种合法组合。
原写法错误原因
- 第一个SQL两次分组都是基于id维度,仅能查询单条余额等于目标值的记录,无法匹配多条组合的场景。
- 第二个SQL直接对全表做聚合,仅能判断全表余额总和是否等于目标,不会遍历不同行的组合。
注意事项
- 子集和属于NP完全问题,当表行数超过20行时计算量会指数级增长,建议提前过滤余额大于目标的行减少计算量。
- 涉及浮点数比较时不要直接用
=判断,增加精度容错区间可以避免二进制存储误差导致的匹配失败。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

