跨多张数据表计算求和值的SQL代码问题咨询
看起来你正在尝试跨多张表计算商品的库存总量和销售总量,我来帮你完善并优化这段SQL代码,同时解释其中的逻辑和需要注意的点:
优化后的完整SQL代码
SELECT barang.id_brg, barang.nm_brg, satuan.jen_sat, kategori.nm_kat, COALESCE(stok_total.stok, 0) AS stok, COALESCE(laku_total.laku, 0) AS laku FROM barang JOIN satuan ON barang.id_sat = satuan.id_sat JOIN kategori ON barang.id_kat = kategori.id_kat LEFT JOIN ( SELECT id_brg, SUM(IFNULL(stok, 0)) AS stok FROM stok_brg GROUP BY id_brg ) AS stok_total ON barang.id_brg = stok_total.id_brg LEFT JOIN ( SELECT id_brg, SUM(IFNULL(dibeli, 0)) AS laku FROM brg_laku GROUP BY id_brg ) AS laku_total ON barang.id_brg = laku_total.id_brg ORDER BY barang.id_brg ASC;
关键优化点和逻辑解释
- 避免笛卡尔积导致的求和错误:
如果你直接在主查询中同时关联stok_brg和brg_laku(哪怕其中一个是子查询),当一个商品有多条库存记录和多条销售记录时,会产生笛卡尔积,导致SUM计算的数值被重复累加,结果偏大。把库存和销售的聚合分别放在独立子查询中,先完成单表的分组求和,再和主表关联,就能彻底避免这个问题。 - 简化子查询逻辑:
子查询不需要再关联barang表,直接针对stok_brg和brg_laku按id_brg分组求和即可,这样查询更高效,逻辑也更清晰。 - 兼容空值处理:
使用COALESCE(或MySQL特有的IFNULL)确保当商品没有库存或销售记录时,返回0而不是NULL,让结果更符合业务预期。 - 显式JOIN语法:
替换原代码中的隐式关联(barang, brg_laku)为显式JOIN,让SQL的可读性和维护性更强。
原代码的潜在问题说明
你的原代码存在两个主要问题:
- 代码未完成(
LEFT JOIN ( ... ) AS brg_laku ON barang.id_brg = brg_...部分截断),需要补全为ON barang.id_brg = brg_laku.id_brg才能运行。 - 即使补全代码,直接在主查询中对
stok_brg.stok求和,会因为和销售子查询的关联产生重复行,导致库存数值计算错误。
内容的提问来源于stack exchange,提问作者Vivi Novita Sari
相关产品推荐
相关产品推荐

