MySQL CASE语句调整:按发票拆分支付类型金额求和问题
问题分析与解决方案
你的SQL核心问题是CASE表达式与SUM函数的嵌套顺序错误,导致无法按支付类型正确求和。当前写法会先判断分组内某一行的支付类型,再对整个分组的金额求和,而非仅统计对应支付类型的金额。另外数据中支付类型存在大小写不一致(如cash和Cash),容易造成统计遗漏。
修正后的SQL代码
SELECT ipc.invoice_id, COUNT(ipc.invoice_id) AS transactions, SUM(CASE WHEN LOWER(ipc.payment_type) = 'cash' THEN ipc.paid ELSE 0 END) AS paid_cash, SUM(CASE WHEN LOWER(ipc.payment_type) = 'insurance' THEN ipc.paid ELSE 0 END) AS paid_ins, SUM(CASE WHEN LOWER(ipc.payment_type) = 'pos' THEN ipc.paid ELSE 0 END) AS paid_pos, SUM(CASE WHEN LOWER(ipc.payment_type) = 'chq' THEN ipc.paid ELSE 0 END) AS paid_chq, SUM(CASE WHEN LOWER(ipc.payment_type) = 'bt' THEN ipc.paid ELSE 0 END) AS paid_bt FROM invoice_payment ipc INNER JOIN invoice i ON ipc.invoice_id = i.id GROUP BY ipc.invoice_id ORDER BY ipc.invoice_id DESC;
关键调整说明
- SUM包裹CASE:先通过CASE筛选出对应支付类型的金额,再对筛选后的结果求和,确保仅统计目标类型的累计金额。
- 统一大小写处理:用
LOWER()函数将支付类型转为小写,避免因大小写差异(如cash/Cash)导致的统计遗漏。 - ELSE 0兜底:无对应支付类型记录时返回0,若需保留NULL可去掉
ELSE 0。 - 明确表别名:给字段添加表前缀(如
ipc.invoice_id),避免多表关联时的字段歧义。
执行以上代码后,发票3的paid_cash会得到50(25+25),paid_pos得到50,与你的期望输出完全一致。
内容的提问来源于stack exchange,提问作者ryan ramsumair
相关产品推荐
相关产品推荐

