SQL按product_id计算entrada总和减salida总和子查询返回多行错误如何解决
错误原因
- 你写的两个子查询都是全表按
producto_id分组后返回所有产品的统计结果,是多行数据集,外层查询每行仅能接收单个数值做减法运算,因此触发#1242错误。 - 不需要拆分为两个独立查询,使用条件聚合即可高效实现需求,性能远高于子查询写法。
推荐实现方案
单表扫描一次即可得到结果,同时自动处理只有entrada/只有salida的场景:
SELECT producto_id, SUM(IF(registro = 'entrada', cantidad, 0)) - SUM(IF(registro = 'salida', cantidad, 0)) AS stock_actual FROM inventario GROUP BY producto_id;
逻辑说明:
- 对每一行记录,判断
registro类型,是入库就累加值,是出库就按0统计,得到所有入库总和 - 同理得到所有出库总和,两者相减就是当前库存
- 当产品没有出库记录时,出库总和为0,直接返回入库总和;没有入库记录时会返回负数库存,符合实际统计逻辑
如果需要兼容更通用的SQL语法(适配PostgreSQL、SQL Server等其他数据库),可以用CASE+COALESCE的写法:
SELECT producto_id, COALESCE(SUM(CASE WHEN registro = 'entrada' THEN cantidad END), 0) - COALESCE(SUM(CASE WHEN registro = 'salida' THEN cantidad END), 0) AS stock_actual FROM inventario GROUP BY producto_id;
子查询写法的修正方案(不推荐,性能差)
如果一定要用子查询实现,需要给子查询加上当前行的producto_id关联条件,确保每个子查询仅返回当前产品的统计值:
SELECT producto_id, (SELECT SUM(cantidad) FROM inventario i2 WHERE i2.producto_id = i1.producto_id AND registro = 'entrada') - COALESCE((SELECT SUM(cantidad) FROM inventario i2 WHERE i2.producto_id = i1.producto_id AND registro = 'salida'), 0) AS stock_actual FROM inventario i1 GROUP BY producto_id;
该写法需要多次扫描表,数据量大时性能远低于条件聚合方案,不建议使用。
内容的提问来源于stack exchange,提问作者Arturo
相关产品推荐
相关产品推荐

