SQL多表审计数据统计:调试CTE查询筛选90天内审计超10次的经理
问题分析与修正方案
原SQL的核心问题
你的代码存在语法、逻辑双重错误,根本无法正确实现需求:
- JOIN用法完全错误:用
INNER JOIN关联三张表,会强制要求经理必须在三个门店都有审计记录才会被纳入统计,直接漏掉只在1个或2个门店做过审计的经理;而且关联后会产生笛卡尔积,导致统计的次数严重虚高。 - 语法顺序错误:
WHERE子句必须放在JOIN之后、GROUP BY之前,你把它放在HAVING后面了,这会直接触发语法报错。 - 缺少分组逻辑:要统计每个经理的审计次数,必须用
GROUP BY manager_name,否则COUNT会统计全表总次数,而非按经理分组。 - 字段冗余且统计对象错误:同时选取三个表的
manager_name和audit_date完全没必要,而且COUNT(manager_name)的统计范围不对,应该基于合并后的所有记录来统计。 - 日期条件不明确:
audit_date没有指定所属表,数据库会报错;另外不同数据库对“当前时间减90天”的写法有差异,比如MySQL用CURDATE() - INTERVAL 90 DAY,PostgreSQL用CURRENT_DATE - INTERVAL '90 days'。
为什么用UNION ALL而不是JOIN?
JOIN是关联匹配,用来把不同表的关联数据拼在同一行,适合需要同时展示多表关联字段的场景,完全不适合这种“合并同结构数据集”的需求。UNION ALL是合并数据集,会把三张表的所有符合条件的记录(经理+审计日期)合并成一个统一的列表,这样才能准确统计每个经理的总审计次数,而且不会过滤掉只在部分门店有记录的经理。
修正后的SQL代码
以通用SQL语法为例(不同数据库可微调日期函数):
WITH total_audit AS ( -- 先合并三张表中90天内的审计记录 SELECT manager_name, audit_date FROM store1 WHERE audit_date >= CURRENT_DATE - INTERVAL '90 days' UNION ALL SELECT manager_name, audit_date FROM store2 WHERE audit_date >= CURRENT_DATE - INTERVAL '90 days' UNION ALL SELECT manager_name, audit_date FROM store3 WHERE audit_date >= CURRENT_DATE - INTERVAL '90 days' ) -- 分组统计总次数,过滤出超过10次的经理 SELECT manager_name, COUNT(*) AS total_audit_count FROM total_audit GROUP BY manager_name HAVING COUNT(*) > 10;
补充说明
- 如果你的数据库不支持
INTERVAL写法(比如SQL Server),可以换成对应写法:DATEADD(DAY, -90, GETDATE()) - 用
UNION ALL而非UNION,因为UNION会自动去重,但如果同一经理在同一门店同一天多次审计,UNION会丢失真实次数,UNION ALL会保留所有原始记录,统计更准确。
内容的提问来源于stack exchange,提问作者hed
相关产品推荐
相关产品推荐

