SQL使用LEFT JOIN统计各国进出口总额的正确写法
问题原因
你写的SQL存在两个导致结果错误的核心问题:
- 关联字段不匹配:
trades表中的seller和buyer字段存储的是企业ID,并非国家名称,直接和companies表的country字段做等值关联完全不符合表结构逻辑,匹配不到正确的交易记录。 - 连接产生笛卡尔积:对
trades表做两次左连接分别统计进出口时,同一国家下的出口记录和进口记录会两两交叉生成重复行,最终求和时金额会被多倍计算,结果完全失真。
正确SQL实现
我们可以通过CTE先分别聚合得到每个国家的进口、出口总额,再关联全量国家列表,既避免笛卡尔积问题,也能保证覆盖所有国家:
WITH all_country AS ( -- 提取所有存在的国家,保证结果全覆盖 SELECT DISTINCT country FROM companies ), country_export AS ( -- 聚合计算每个国家的出口总额:卖家所属国家的销售金额 SELECT c.country, SUM(t.value) AS export FROM trades t INNER JOIN companies c ON t.seller = c.id GROUP BY c.country ), country_import AS ( -- 聚合计算每个国家的进口总额:买家所属国家的采购金额 SELECT c.country, SUM(t.value) AS import FROM trades t INNER JOIN companies c ON t.buyer = c.id GROUP BY c.country ) SELECT ac.country, -- 无进出口记录的国家金额补0,避免返回NULL COALESCE(ce.export, 0) AS export, COALESCE(ci.import, 0) AS import FROM all_country ac LEFT JOIN country_export ce ON ac.country = ce.country LEFT JOIN country_import ci ON ac.country = ci.country ORDER BY ac.country ASC;
逻辑说明
- 先单独聚合进出口金额再做关联,从根源上避免了同一张交易表多次连接产生的交叉重复问题,计算结果准确。
- 以全量去重国家列表为基表做左连接,不会遗漏任何存在的国家,即使该国家没有任何进口或出口记录。
- 通过
COALESCE函数将空值转换为0,符合统计类结果的展示规范。
内容的提问来源于stack exchange,提问作者Gooner Coder
相关产品推荐
相关产品推荐

