Sas 基于非轴列的Proc sql子查询返回NOTNULL

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语

下面是从实际应用程序派生的示例代码。有两个数据集——“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。谢谢大家!

代码如下:

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;