排查查询特定条件未通知到期客户的SQL语句故障
解决会员到期通知筛选问题:找出未收到指定通知的目标客户
我来帮你梳理下原SQL的问题,然后给出符合需求的正确写法。你的核心需求是找出未来两个月内到期、是会员非管理员、今日未收到类型6通知的客户,但原SQL的几个逻辑错误导致没得到正确结果。
原SQL的问题分析
- LEFT JOIN被错误转成内连接:你在WHERE子句里加了
no_type = '6'和DATE_FORMAT(no_date,'%Y-%m-%d') = '2018-01-09',这会把所有没有对应通知记录的客户(也就是你要找的目标)过滤掉——因为LEFT JOIN后无匹配的记录中这些字段是NULL,NULL和任何值比较都不成立,相当于变成了INNER JOIN,完全违背了“找无通知记录”的需求。 - 到期日期筛选太严格:原SQL里
CURRENT_DATE = expiry_date - INTERVAL '2' MONTH只筛选刚好到期前两个月当天的客户,而你要的是“两个月内到期”的客户,也就是当前日期处于「到期日减2个月」到「到期日」之间的所有客户。
正确的SQL写法
这里推荐用NOT EXISTS子查询来实现,逻辑更直观,性能也更优:
SELECT c.customer_id, c.customer_token, c.customer_name, c.expiry_date, DATE_FORMAT(c.expiry_date - INTERVAL 2 MONTH, '%Y-%m-%d') AS ExpireLim FROM customer c WHERE -- 1. 客户是会员而非管理员 c.is_member = 1 AND c.is_admin = 0 -- 2. 客户token有效(非空且不是占位符) AND c.customer_token != '' AND c.customer_token != 'device_token' -- 3. 当前日期处于到期日减2个月到到期日之间(未来两个月内到期) AND CURRENT_DATE BETWEEN c.expiry_date - INTERVAL 2 MONTH AND c.expiry_date -- 4. 今日未收到类型为6的通知 AND NOT EXISTS ( SELECT 1 FROM notification n WHERE n.no_customer_id = c.customer_id AND n.no_type = '6' AND DATE_FORMAT(n.no_date, '%Y-%m-%d') = '2018-01-09' );
逻辑说明
- 先通过
WHERE子句筛选出符合基础条件的客户:会员、非管理员、有效token、未来两个月内到期。 - 再用
NOT EXISTS排除掉今日已经收到类型6通知的客户——只要子查询能找到对应记录,就说明该客户已收到通知,会被排除;反之则保留,正好符合你的需求。
用这个SQL查询测试数据时,Jiren和Lee因为有对应的通知记录会被排除,剩下的客户ID3和4就是你要的结果。
内容的提问来源于stack exchange,提问作者Architect - Hitesh
相关产品推荐
相关产品推荐

