Sas 基于非轴列的Proc sql子查询返回NOTNULL
下面是从实际应用程序派生的示例代码。有两个数据集——“aa”表示查询,“bb”表示子查询。数据集“aa”中的“m”列与数据集“bb”中的“y”列匹配。此外,“aa”表上的“yy”列的值为30。数据集“aa”中的列“m”在其一行中包含值“30”,而数据集“bb”中的列“y”不包含值。First proc sql根据“m”列中的匹配值,使用“bb”表的“y”列到子集表“aa”的值。这是一个正确的查询,并按预期生成结果。第二个proc sql块在子查询中故意将列“y”拼写为“yy”,该行以where语句开头。否则,整个proc sql块与第一个相同。假设数据集bb上没有“yy”列,我希望出现一条错误消息,整个查询将失败。但是,它确实返回一行,没有失败或错误消息。仔细看,它实际上使用了表“aa”中的“yy”列(参见日志输出中的树)。我认为这是不正确的行为。如果您有什么意见或解释,我将不胜感激。否则,我可能应该将其作为错误报告给SAS。谢谢大家! 代码如下:Sas 基于非轴列的Proc sql子查询返回NOTNULL,sas,proc-sql,Sas,Proc Sql,下面是从实际应用程序派生的示例代码。有两个数据集——“aa”表示查询,“bb”表示子查询。数据集“aa”中的“m”列与数据集“bb”中的“y”列匹配。此外,“aa”表上的“yy”列的值为30。数据集“aa”中的列“m”在其一行中包含值“30”,而数据集“bb”中的列“y”不包含值。First proc sql根据“m”列中的匹配值,使用“bb”表的“y”列到子集表“aa”的值。这是一个正确的查询,并按预期生成结果。第二个proc sql块在子查询中故意将列“y”拼写为“yy”,该行以where语
options
msglevel = I
;
data aa;
do i=1 to 20;
m=i*5;
yy=30;
output;
end;
run;
data bb;
do i=10 to 20;
y=i*5;
output;
end;
run;
option DEBUG=JUNK ;
/*Correct sql command*/
proc sql _method
_tree
;
create table cc as
select *
from aa
where m in (select y from bb)
;quit;
/*Incorrect sql command - column "yy" in not on "bb" table"*/
proc sql _method
_tree;
create table dd as
select *
from aa
where m in (select yy from bb)
;quit;
下面是sql树的日志:
119 options
120 msglevel = I
121 ;
122 data aa;
123 do i=1 to 20;
124 m=i*5;
125 yy=30;
126 output;
127 end;
128 run;
NOTE: The data set WORK.AA has 20 observations and 3 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
129
130 data bb;
131 do i=10 to 20;
132 y=i*5;
133 output;
134 end;
135 run;
NOTE: The data set WORK.BB has 11 observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
136 option DEBUG=JUNK ;
137
138 /*Correct sql command*/
139 proc sql _method
140 _tree
141 ;
142 create table cc as
143 select *
144 from aa
145 where m in (select y from bb)
146 ;
NOTE: SQL execution methods chosen are:
sqxcrta
sqxfil
sqxsrc( WORK.AA )
NOTE: SQL subquery execution methods chosen are:
sqxsubq
sqxsrc( WORK.BB )
Tree as planned.
/-SYM-V-(aa.i:1 flag=0001)
/-OBJ----|
| |--SYM-V-(aa.m:2 flag=0001)
| \-SYM-V-(aa.yy:3 flag=0001)
/-FIL----|
| | /-SYM-V-(aa.i:1 flag=0001)
| | /-OBJ----|
| | | |--SYM-V-(aa.m:2 flag=0001)
| | | \-SYM-V-(aa.yy:3 flag=0001)
| |--SRC----|
| | \-TABL[WORK].aa opt=''
| | /-SYM-V-(aa.m:2)
| \-IN-----|
| | /-SYM-V-(bb.y:2 flag=0001)
| | /-OBJ----|
| | /-SRC----|
| | | \-TABL[WORK].bb opt=''
| \-SUBC---|
--SSEL---|
NOTE: Table WORK.CC created, with 11 rows and 3 columns.
146! quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.03 seconds
cpu time 0.03 seconds
147
148
149 /*Incorrect sql command - column "yy" in not on "bb" table"*/
150 proc sql _method
151 _tree;
152 create table dd as
153 select *
154 from aa
155 where m in (select yy from bb)
156 ;
NOTE: SQL execution methods chosen are:
sqxcrta
sqxfil
sqxsrc( WORK.AA )
NOTE: SQL subquery execution methods chosen are:
sqxsubq
sqxreps
sqxsrc( WORK.BB )
Tree as planned.
/-SYM-V-(aa.i:1 flag=0001)
/-OBJ----|
| |--SYM-V-(aa.m:2 flag=0001)
| \-SYM-V-(aa.yy:3 flag=0001)
/-FIL----|
| | /-SYM-V-(aa.i:1 flag=0001)
| | /-OBJ----|
| | | |--SYM-V-(aa.m:2 flag=0001)
| | | \-SYM-V-(aa.yy:3 flag=0001)
| |--SRC----|
| | \-TABL[WORK].aa opt=''
| | /-SYM-V-(aa.m:2)
| \-IN-----|
| | /-SYM-A-(#TEMA001:1 flag=0035)
| | /-OBJ----|
| | /-REPS---|
| | | |--empty-
| | | |--empty-
| | | | /-OBJ----|
| | | |--SRC----|
| | | | \-TABL[WORK].bb opt=''
| | | |--empty-
| | | |--empty-
| | | | /-SYM-A-(#TEMA001:1 flag=
0035)
| | | | /-ASGN---|
| | | | | \-SUBP(1)
| | | \-OBJE---|
| \-SUBC---|
| \-SYM-V-(aa.yy:3)
--SSEL---|
NOTE: Table WORK.DD created, with 1 rows and 3 columns.
156! quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
以下是数据集:
aa:
i m yy
1 5 30
2 10 30
3 15 30
4 20 30
5 25 30
6 30 30
7 35 30
8 40 30
9 45 30
10 50 30
11 55 30
12 60 30
13 65 30
14 70 30
15 75 30
16 80 30
17 85 30
18 90 30
19 95 30
20 100 30
bb:
i y
10 50
11 55
12 60
13 65
14 70
15 75
16 80
17 85
18 90
19 95
20 100
我同意,这看起来很奇怪,很可能是个bug。我能够从您在SAS 9.4和SAS 9.1.3中提供的代码中复制此代码,这将使它至少有12年的历史 特别是,我感兴趣的是在创建DD表时从
\u方法
选项获得的这一点输出,而不是在创建CC表时:
NOTE: SQL subquery execution methods chosen are:
sqxsubq
sqxreps <--- What is this doing?
sqxsrc( WORK.BB )
我以前从未在输出的相应位中看到过sqxreps
或reps
。我通过谷歌搜索找到的任何一篇文章都没有列出这两个问题(事实上,这个问题目前是sas+sqxreps在谷歌上唯一的热门话题):
引用其中第一条:
Codes Description
sqxcrta Create table as Select
Sqxslct Select
sqxjsl Step loop join (Cartesian)
sqxjm Merge join
sqxjndx Index join
sqxjhsh Hash join
sqxsort Sort
sqxsrc Source rows from table
sqxfil Filter rows
sqxsumg Summary stats with GROUP BY
sqxsumn Summary stats with no GROUP BY
根据一点快速测试,如果AA中的变量名在引用表BB的子查询中重复多次,则无论使用的变量和表名如何,这种情况似乎都会发生。如果您在AA中有一个名为YYY的变量,但在BB中有一个名为YY的变量,或者更一般地说,当您在BB中有一个变量,其名称最初与AA中相应变量的名称相同,但随后继续一个或多个字符时,也会发生这种情况
从这一点上,我猜在SQL解析器的某个点上,有人使用了like
操作符,而不是检查变量名是否相等,不知何故,这种语法触发了proc SQL
中未记录或不完整的“功能”
更一般情况的一个例子:
options
msglevel = I
;
data aa;
do i=1 to 20;
m=i*5;
myvar_plus_suffix=30;
output;
end;
run;
data bb;
do i=10 to 20;
myvar=i*5;
output;
end;
run;
option DEBUG=JUNK ;
/*Incorrect sql command - column "yy" in not on "bb" table"*/
proc sql _method
_tree;
create table dd as
select *
from aa
where m in (select myvar_plus_suffix from bb)
;quit;
以下是SAS支持部门的回复。 您看到的内容与PROC SQL中的列范围相关 procsql支持corelated子查询。相关子查询引用“外部”表中的列,然后可以将该列与“内部”表中的列进行比较。PROC SQL不要求使用完全限定的列名。因此,如果它在子查询中看到内部表(子查询中引用的表)中不存在的列,它将在“外部”表中查找该列,如果找到该列,则使用该值 如果使用完全限定的列名,则会出现预期的错误,例如:
proc sql;
create table dd as
select *
from aa as outer
where outer.m in (select inner.yyy from bb as inner);
quit;
非常感谢。我也无法在任何地方找到SQXREP文档。但是,我无法重现“AA中名为YYY但BB中名为YY的变量”的错误,或者更一般地说,当BB中有一个变量的名称最初与AA中相应变量的名称相同,但随后继续一个或多个字符时。我可以请你分享一些代码吗?非常感谢。按要求添加示例。好的,我现在明白你的意思了。我不认为这与“like”变量名有关,因为即使您将BB上的“myvar”更改为其他任何内容(比如“fghghj”),它仍然会返回相同的结果。因此,它不必与AA上的列相似。但感谢您的输入,这将是SAS支持现在。感谢更新-这是一个微妙的相关子查询,我当然不欣赏。我想知道这在大多数其他sql实现中是否相同?
proc sql;
create table dd as
select *
from aa as outer
where outer.m in (select inner.yyy from bb as inner);
quit;