Proc SQL neT 运算符在 WHERE 中未正确计算
Proc SQL neT operator does not evaluate properly in WHERE
无法弄清楚为什么 WHERE 子句不过滤所选行。
neT
评估是赋值期间的更正,但 不是 在 WHERE
子句中工作(已选择所有 5 行!)
data a;
input a $ b $; datalines;
abcd abdef
abcd abcdefg
abcdef abcd
xxyyzz .
. xxyyzz
run;
proc sql;
create table b as
select *
, a neT b as neT
, a eqT b as eqT
from a
where a neT b
;
quit;
Table B
你需要剥离
where strip(a) neT strip(b)
这也与主题相关
44 data _null_;
45 a='12';
46 b='1 ';
47 x = a eq: b;
48 z = strip(a) eq: strip(b);
49 put _all_;
50 run;
a=12 b=1 x=0 z=1 _ERROR_=0 _N_=1
这是令人困惑的记录,但可能是正确的行为(虽然我不知道为什么)。
在documentation of the SQL truncating expressions中:
The Base SAS WHERE processor handles truncated comparisons differently than PROC SQL does. The Base SAS WHERE processor truncates comparisons based on the actual length of a string, even if a string includes blanks at the end. PROC SQL trims trailing blanks from the string values before it truncates comparisons. PROC SQL truncates string comparisons similar to other SQL processors that conform, in various degrees, to the INCITS/ISO/IEC/ANSI SQL:2011 Standards.
现在,这当然令人困惑,因为文档说 base SAS Where
会按照您在第二个示例中描述的方式工作,即:
data b;
set a;
where a ne: b;
run;
根据文档,预计 return 5 行。然而,目前还不清楚为什么 SQL where 的行为方式是这样的,而不是文档所说的 SQL 处理事情的方式 - 但它也并不奇怪,因为我一直理解 where
通常在 PROC SQL 和数据步骤中以相同的方式工作。您可能想尝试通过技术支持提高轨道 - 或者,如果您不知道该怎么做,我可以验证这是有意的行为,而不是无意的。
当然,为什么 这被认为是正确的行为(即使在数据步骤 where
中),我不知道。它使得截断表达式基本上无法用于相互比较变量,而无需向两者添加 strip
或 trim
...无论如何,这是其他模式下的正常行为。我猜这是某种失控的向后兼容性问题,我鼓励您创建一个 SASWare Ballot idea 来改变这种行为。
您可以解决此问题,正如 Data _Null 所解释的那样 - 通过在两个参数上使用 strip
,或者 trim
- 或者,如果您实际上 是 在列表达式中使用 neT
以及 where
,您可以使用 calculated
:
proc sql;
create table b as
select *
, a neT b as _neT
, a eqT b as _eqT
from a
where calculated _net eq 1
;
quit;
无法弄清楚为什么 WHERE 子句不过滤所选行。
neT
评估是赋值期间的更正,但 不是 在 WHERE
子句中工作(已选择所有 5 行!)
data a;
input a $ b $; datalines;
abcd abdef
abcd abcdefg
abcdef abcd
xxyyzz .
. xxyyzz
run;
proc sql;
create table b as
select *
, a neT b as neT
, a eqT b as eqT
from a
where a neT b
;
quit;
Table B
你需要剥离
where strip(a) neT strip(b)
这也与主题相关
44 data _null_;
45 a='12';
46 b='1 ';
47 x = a eq: b;
48 z = strip(a) eq: strip(b);
49 put _all_;
50 run;
a=12 b=1 x=0 z=1 _ERROR_=0 _N_=1
这是令人困惑的记录,但可能是正确的行为(虽然我不知道为什么)。
在documentation of the SQL truncating expressions中:
The Base SAS WHERE processor handles truncated comparisons differently than PROC SQL does. The Base SAS WHERE processor truncates comparisons based on the actual length of a string, even if a string includes blanks at the end. PROC SQL trims trailing blanks from the string values before it truncates comparisons. PROC SQL truncates string comparisons similar to other SQL processors that conform, in various degrees, to the INCITS/ISO/IEC/ANSI SQL:2011 Standards.
现在,这当然令人困惑,因为文档说 base SAS Where
会按照您在第二个示例中描述的方式工作,即:
data b;
set a;
where a ne: b;
run;
根据文档,预计 return 5 行。然而,目前还不清楚为什么 SQL where 的行为方式是这样的,而不是文档所说的 SQL 处理事情的方式 - 但它也并不奇怪,因为我一直理解 where
通常在 PROC SQL 和数据步骤中以相同的方式工作。您可能想尝试通过技术支持提高轨道 - 或者,如果您不知道该怎么做,我可以验证这是有意的行为,而不是无意的。
当然,为什么 这被认为是正确的行为(即使在数据步骤 where
中),我不知道。它使得截断表达式基本上无法用于相互比较变量,而无需向两者添加 strip
或 trim
...无论如何,这是其他模式下的正常行为。我猜这是某种失控的向后兼容性问题,我鼓励您创建一个 SASWare Ballot idea 来改变这种行为。
您可以解决此问题,正如 Data _Null 所解释的那样 - 通过在两个参数上使用 strip
,或者 trim
- 或者,如果您实际上 是 在列表达式中使用 neT
以及 where
,您可以使用 calculated
:
proc sql;
create table b as
select *
, a neT b as _neT
, a eqT b as _eqT
from a
where calculated _net eq 1
;
quit;