SQL查询判断ODCalls表中ANI号码当日是否首次来电并返回0/1标识
原SQL问题排查
你写的SQL存在几个核心错误,直接导致结果不符合预期:
- 外层查询缺失
WHERE关键字,语法本身不合法,无法正常执行 - 子查询时间逻辑完全写反:两个条件都是
>=,实际筛选出的是6月7日23:59:59之后的来电记录,完全不是“当日之前的历史记录” - 用
NOT IN做判断存在风险:如果子查询返回的ANI里存在NULL值,会导致整个NOT IN逻辑判断失效,返回结果为空 - 返回逻辑不符合需求:只查询了当日无历史记录的号码,没有按要求给每个号码返回是否有历史记录的0/1标记
正确实现方案
核心逻辑分三步:
- 先圈定统计当日所有产生来电的ANI号码范围
- 匹配这些号码在统计日0点之前是否存在通话记录
- 用条件判断生成0/1标记,存在历史记录返回1,不存在返回0
方案1:返回当日所有来电号码的去重结果+标记
适合只需要号码维度统计结果的场景:
-- 示例统计日为2022-06-08,可按需替换日期 SELECT cur.ANI AS mobile, CASE WHEN hist.ANI IS NOT NULL THEN 1 ELSE 0 END AS has_hist_call FROM ( -- 取当日所有去重来电号码 SELECT DISTINCT ANI FROM ODCalls WHERE CallLocalTime >= '2022-06-08 00:00:00' AND CallLocalTime < '2022-06-09 00:00:00' ) cur LEFT JOIN ( -- 取统计日之前所有出现过的去重号码 SELECT DISTINCT ANI FROM ODCalls WHERE CallLocalTime < '2022-06-08 00:00:00' ) hist ON cur.ANI = hist.ANI;
方案2:返回当日所有通话明细+标记
适合需要保留每一条通话记录,同时给记录打标的场景,用窗口函数实现更简洁:
SELECT *, CASE WHEN MIN(CallLocalTime) OVER(PARTITION BY ANI) < '2022-06-08 00:00:00' THEN 1 ELSE 0 END AS has_hist_call FROM ODCalls WHERE CallLocalTime >= '2022-06-08 00:00:00' AND CallLocalTime < '2022-06-09 00:00:00';
注意事项
- 时间范围判断建议用
< 次日00:00:00代替<= 当日23:59:59,避免漏掉带毫秒/微秒精度的时间记录(比如2022-06-08 23:59:59.452这类时间会被后者的判断条件漏掉) - 不要用
NOT IN做跨表匹配,遇到NULL值会出现非预期结果,优先用左连接、NOT EXISTS替代
内容的提问来源于stack exchange,提问作者Mohamed El Habchi
相关产品推荐
相关产品推荐

