You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL查询求和结果异常:收入与支出表关联查询错误

问题根源

你的查询使用INNER JOIN时未指定月份关联条件,且仅过滤了收入表的年份,这会导致收入表与支出表产生笛卡尔积——每一条收入记录都会和所有支出记录配对。最终求和时,收入总额会被重复计算(重复次数等于对应月份支出记录的数量),支出总额同理,因此求和结果远大于实际值。

解决方案

正确的思路是先分别对收入表、支出表按月份独立统计求和,再将两个统计结果按月份关联,确保每个月份的收入和支出是单独计算后再合并的。

方法1:子查询+全连接(推荐)

如果你的MySQL版本支持FULL OUTER JOIN(MySQL 8.0及以上),可以用CTE先拆分统计:

WITH monthly_income AS (
    SELECT MONTH(date) AS month, SUM(total_amount) AS income
    FROM income
    WHERE YEAR(date) = YEAR(CURRENT_DATE)
    GROUP BY MONTH(date)
),
monthly_outcome AS (
    SELECT MONTH(date) AS month, SUM(total_amount) AS outcome
    FROM outcome
    WHERE YEAR(date) = YEAR(CURRENT_DATE)
    GROUP BY MONTH(date)
)
SELECT
    COALESCE(mi.month, mo.month) AS month,
    COALESCE(mi.income, 0) AS income,
    COALESCE(mo.outcome, 0) AS outcome
FROM monthly_income mi
FULL OUTER JOIN monthly_outcome mo ON mi.month = mo.month
ORDER BY month;

若MySQL版本不支持全连接,可通过LEFT JOIN + UNION RIGHT JOIN实现相同效果:

SELECT
    COALESCE(i.month, o.month) AS month,
    COALESCE(i.income, 0) AS income,
    COALESCE(o.outcome, 0) AS outcome
FROM
    (SELECT MONTH(date) AS month, SUM(total_amount) AS income FROM income WHERE YEAR(date) = YEAR(CURRENT_DATE) GROUP BY MONTH(date)) i
LEFT JOIN
    (SELECT MONTH(date) AS month, SUM(total_amount) AS outcome FROM outcome WHERE YEAR(date) = YEAR(CURRENT_DATE) GROUP BY MONTH(date)) o ON i.month = o.month
UNION
SELECT
    COALESCE(i.month, o.month) AS month,
    COALESCE(i.income, 0) AS income,
    COALESCE(o.outcome, 0) AS outcome
FROM
    (SELECT MONTH(date) AS month, SUM(total_amount) AS income FROM income WHERE YEAR(date) = YEAR(CURRENT_DATE) GROUP BY MONTH(date)) i
RIGHT JOIN
    (SELECT MONTH(date) AS month, SUM(total_amount) AS outcome FROM outcome WHERE YEAR(date) = YEAR(CURRENT_DATE) GROUP BY MONTH(date)) o ON i.month = o.month
ORDER BY month;

方法2:UNION ALL后聚合

将收入、支出数据合并为统一结构,再按月份和类型聚合后转成列:

SELECT
    month,
    SUM(CASE WHEN type = 'income' THEN amount ELSE 0 END) AS income,
    SUM(CASE WHEN type = 'outcome' THEN amount ELSE 0 END) AS outcome
FROM (
    SELECT
        MONTH(date) AS month,
        total_amount AS amount,
        'income' AS type
    FROM income
    WHERE YEAR(date) = YEAR(CURRENT_DATE)
    UNION ALL
    SELECT
        MONTH(date) AS month,
        total_amount AS amount,
        'outcome' AS type
    FROM outcome
    WHERE YEAR(date) = YEAR(CURRENT_DATE)
) AS combined
GROUP BY month
ORDER BY month;
关键说明
  • COALESCE函数用于处理“某月份只有收入/只有支出”的场景,避免结果出现NULL,统一显示为0。
  • 必须先对单表聚合再关联,彻底避免笛卡尔积导致的重复计算。
  • 两个表都要添加年份过滤条件,防止跨年度数据干扰统计结果。

内容的提问来源于stack exchange,提问作者Zeu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 07:40:38