SAS Proc SQL中neT运算符在WHERE子句无法正确求值问题咨询
异常产生原因
这是SAS中PROC SQL对neT这类带T后缀的截断比较运算符的求值逻辑差异导致的:
- 出现在SELECT列表的列赋值逻辑中时,
neT会按每行两个变量的实际非缺失字符串长度,取较短值的长度截断长字符串后再比较,符合你对截断比较的预期。 - 出现在PROC SQL的WHERE子句中时,
neT会提前取两个字符变量的定义长度而非每行的实际值长度计算截断长度。你示例中的a、b两个变量都是通过input a $ b $的默认规则定义,字符长度均为8位,定义长度完全一致,因此WHERE子句中的a neT b等价于直接执行a ne b,不会做任何截断。
这种差异就导致了:比如第三个观测a=abcdef、b=abcd,按实际值截断后两者相等,neT返回0,但WHERE子句按全8位对比(字符串后补空格)判定两者不等,返回真,该行就会被选中。同时SAS中任意值和缺失值做不等比较都返回真,最后两行也会被保留,最终输出全5行数据,看起来就像WHERE子句未生效。
解决方法
可以通过三种方案规避这个逻辑差异:
- 方案1:子查询先计算截断比较标记,外层用标记列过滤,确保使用SELECT侧的计算结果
proc sql; create table b as select * from ( select * , a neT b as neT , a eqT b as eqT from a ) t where neT = 1 ; quit;
- 方案2:手动实现截断比较逻辑,强制按实际值长度做截断,保证WHERE子句逻辑和预期一致
proc sql; create table b as select * , a neT b as neT , a eqT b as eqT from a where substrn(a,1,min(lengthn(a),lengthn(b))) ne substrn(b,1,min(lengthn(a),lengthn(b))) ; quit;
- 方案3:改用DATA步做过滤,DATA步中
neT运算符在赋值和WHERE子句中的逻辑统一,都是按实际值长度截断
data b; set a; neT = a neT b; eqT = a eqT b; if a neT b; run;
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

