两表异常报表排查:已登录未扫描箱查询SQL错误分析
咱们来一步步梳理你遇到的问题:你的SQL返回了已扫描的箱子,核心是匹配逻辑和几个细节出了问题,具体如下:
核心匹配逻辑错误:你在
NOT EXISTS子句里用a.box = b.boxname做匹配,但scan表的boxname是箱号+批次的拼接值,而login表的a.box只是单独的箱号,这完全没法正确匹配!正确的做法应该是把login表的box和batch拼接后,再和b.boxname对比,也就是用CONCAT_WS('-', a.box, a.batch) = b.boxname。Profid取值不一致的疑问:你筛选
login表时用的是profid = '46',但scan表却用profid = '6'——这大概率是笔误吧?如果这两个表的profid应该对应同一个业务主体,这种不一致会导致你根本匹配不到本该对应的扫描记录,进而让已扫描的箱子被错误判定为未扫描。时间格式的潜在风险:你的时间条件里写了
'2018/01/01 00:00:01am'和'2018/05/25 23:59:59 PM',注意23:59:59本身就是深夜,再加PM属于冗余,而且不同数据库对这种非标准时间字符串的解析可能出错,建议换成标准格式'2018-01-01 00:00:01'和'2018-05-25 23:59:59'。DISTINCT的冗余性:如果
login表中box+batch的组合本身是唯一的,那DISTINCT完全没必要加,反而会额外消耗性能。
修正后的SQL语句
SELECT CONCAT_WS('-', box, batch) AS boxname FROM login a WHERE a.profid = '46' AND dt BETWEEN '2018-01-01 00:00:01' AND '2018-05-25 23:59:59' AND NOT EXISTS ( SELECT 1 FROM scan b WHERE b.profid = '46' -- 这里请确认profid取值,若业务上确实是6则保留 AND CONCAT_WS('-', a.box, a.batch) = b.boxname )
另外要注意:如果scan表的boxname拼接用的分隔符不是-(比如下划线、空格),一定要同步调整CONCAT_WS里的分隔符,必须和实际存储的格式完全一致才能正确匹配。
内容的提问来源于stack exchange,提问作者user3906930

