双表查询:如何统计含金额<20行项目的不重复发票数量
解决发票重复统计的SQL问题
你现在碰到的问题很典型:因为部分发票有多个金额小于20的行项目,关联两张表后同一个发票ID会重复出现在结果集里,直接COUNT(a.invoice_id)就把这些重复的ID都算进去了,导致统计数虚高。
先看你原来的SQL:
SELECT COUNT(a.invoice_id) FROM invoices a, invoice_line_items b WHERE b.line_item_amount < 20;
这里还要注意一个隐藏问题——你用了隐式关联但没写表之间的关联条件(比如a.invoice_id = b.invoice_id),这会产生笛卡尔积,查询结果本身就不符合逻辑,不过核心的重复计数问题确实是因为同一发票的多行符合条件记录导致的。
要解决重复统计的问题,DISTINCT关键字需要放在COUNT()括号内的字段前面,确保只统计唯一的发票ID。同时一定要补上表的关联条件,修正后的SQL有两种常用写法:
写法一:在COUNT中直接使用DISTINCT
SELECT COUNT(DISTINCT a.invoice_id) FROM invoices a INNER JOIN invoice_line_items b ON a.invoice_id = b.invoice_id WHERE b.line_item_amount < 20;
这里COUNT(DISTINCT a.invoice_id)会先对所有符合条件的发票ID去重,再统计数量,完美避免了同一发票被多次计数的问题。
写法二:通过子查询先获取唯一发票ID再统计
如果你觉得子查询的逻辑更清晰,也可以先从行项目表中筛选出所有符合条件的唯一发票ID,再统计总数:
SELECT COUNT(invoice_id) FROM ( SELECT DISTINCT invoice_id FROM invoice_line_items WHERE line_item_amount < 20 ) AS valid_invoices;
这种写法先在子查询里完成去重和筛选,外层只需要统计去重后的ID数量,结果和第一种写法一致,选择哪种全凭你个人的阅读习惯。
最后建议尽量使用显式的INNER JOIN语法代替隐式的逗号分隔表,这样SQL的逻辑更清晰,也不容易遗漏关联条件。
内容的提问来源于stack exchange,提问作者tobylol
相关产品推荐
相关产品推荐

