为什么T-SQL的WHERE NOT IN会返回已被过滤的元素
问题根因
- 逻辑运算符优先级错误是核心诱因:SQL执行逻辑中
AND运算符优先级高于OR,现有WHERE条件的实际执行逻辑被拆解为:
这就导致(NOT IN(子查询结果) AND 号码前缀匹配767512%) OR (号码前缀匹配767520% AND 号码不在固定过滤列表)767512%前缀的号码完全不受后面固定过滤列表的约束,只要满足前两个条件就会返回,因此76751219会出现在结果中。 - 潜在问题1:两个过滤条件中对号码的清洗规则不统一,一处用
REPLACE(PhoneNumber, ' ', ''),另一处用LTRIM(REPLACE(PhoneNumber, ' ', '')),可能存在尾部空格导致匹配失效的隐患。 - 潜在问题2:如果
OPENJSON解析出的Number字段存在NULL值,NOT IN会直接返回空结果,也可能导致过滤逻辑失效。
修复方案
调整条件括号包裹逻辑,统一号码清洗规则,修正后语句如下:
DECLARE @json NVARCHAR(MAX) SET @json = (SELECT PHONE_DATA FROM EFP_JSON WHERE ID = 1) SELECT PhoneNumber FROM EFP_PhoneNumberSeries WHERE -- 统一号码清洗规则 REPLACE(PhoneNumber, ' ', '') NOT IN ( SELECT PhoneNumbers.Number FROM OPENJSON(@json) WITH ( Localnumber VARCHAR(50) '$.Localnumber', Name VARCHAR(50) '$.Name', Email VARCHAR(50) '$.Email', PhoneNumbers nvarchar(max) '$.PhoneNumbers' AS JSON, Phones nvarchar(max) '$.Phones' AS JSON ) as UserInfo CROSS APPLY OPENJSON(PhoneNumbers) WITH( Number nvarchar(100) '$.Number', LineName nvarchar(100) '$.LineName', GotoLocalNumber nvarchar(100) '$.GotoLocalNumber', BelongsTo nvarchar(100) '$.BelongsTo' ) as PhoneNumbers CROSS APPLY OPENJSON(Phones) WITH( description nvarchar(100) '$.description' ) as description -- 排除NULL值避免NOT IN失效 WHERE PhoneNumbers.Number IS NOT NULL ) -- 用括号包裹前缀匹配条件,确保优先级正确 AND ( REPLACE(PhoneNumber, ' ', '') LIKE '767512%' OR REPLACE(PhoneNumber, ' ', '') LIKE '767520%' ) -- 固定过滤列表作用于所有符合前缀的号码 AND REPLACE(PhoneNumber, ' ', '') NOT IN ( '76752000','76752005','76752006','76752007','76752008','76752010', '76752011','76752012','76751219','76751221','76752022','76752058', '76752060','76752063','76752097','76752098' );
内容的提问来源于stack exchange,提问作者Stig Kølbæk
相关产品推荐
相关产品推荐

