MySQL双表关联查询实现收入减支出计算总收益
解决MySQL月度收支关联及总收益计算问题
看起来你目前的SQL是分开查询两个表的聚合结果,没有把它们关联起来,这就是为什么得不到正确的合并结果。我来帮你修正这个查询,实现你要的月度收支匹配和总收益计算。
首先,我们需要明确两个关键点:
- 按年份+月份来关联两个表的数据(因为你的日期格式是MM-DD-YY,要确保同一年的同一个月数据匹配)
- 处理可能存在的“当月有收入但无支出”或者“有支出但无收入”的情况(用
COALESCE来避免NULL值导致计算错误)
第一步:拆解需求对应的SQL逻辑
- 先分别对收入表和支出表按月份聚合(如果每个月只有一条记录,聚合可以简化,但用
SUM更通用,适配多记录场景) - 通过年份和月份将两个聚合后的结果关联
- 计算总收益:
Earnings - Expenses,用COALESCE把NULL支出转为0,避免计算出NULL
最终查询语句
SELECT -- 用收入表的月度日期作为显示日期,也可以统一显示为当月第一天/最后一天 me.`Monthly Date` AS `Monthly Date`, me.earnings_total AS `Earnings`, COALESCE(me_exp.expenses_total, 0) AS `Expenses`, (me.earnings_total - COALESCE(me_exp.expenses_total, 0)) AS `Total Earnings` FROM -- 先聚合收入表的月度数据 (SELECT `Monthly Date`, SUM(`Earnings`) AS earnings_total, YEAR(`Monthly Date`) AS year_val, MONTH(`Monthly Date`) AS month_val FROM `Monthly Earnings` GROUP BY year_val, month_val, `Monthly Date`) AS me LEFT JOIN -- 再聚合支出表的月度数据 (SELECT SUM(`Cost Price`) AS expenses_total, YEAR(`Purchase Date`) AS year_val, MONTH(`Purchase Date`) AS month_val FROM `Monthly Expenses` GROUP BY year_val, month_val) AS me_exp ON me.year_val = me_exp.year_val AND me.month_val = me_exp.month_val;
针对你示例数据的简化版本
如果你的每个月在两个表里都只有一条记录,不需要聚合的话,可以简化成更直接的关联:
SELECT me.`Monthly Date`, me.`Earnings`, COALESCE(me_exp.`Cost Price`, 0) AS `Expenses`, (me.`Earnings` - COALESCE(me_exp.`Cost Price`, 0)) AS `Total Earnings` FROM `Monthly Earnings` me LEFT JOIN `Monthly Expenses` me_exp ON YEAR(me.`Monthly Date`) = YEAR(me_exp.`Purchase Date`) AND MONTH(me.`Monthly Date`) = MONTH(me_exp.`Purchase Date`);
为什么你的原SQL不行?
你之前的代码是分开写了两个独立的聚合查询,没有用JOIN把它们关联起来,所以没办法把同一月份的收入和支出放在同一行里计算总收益。上面的查询通过子查询聚合后再关联,就解决了这个问题。
内容的提问来源于stack exchange,提问作者Pol Laure




