数据集观测的获取有2个特别简单的方法,SAS内置了两个系统宏变量,一个叫sqlobs,一个叫sysnobs。
sqlobs:这个宏变量可以获取上一次sql运行的后的观测数。但前提是sql运行必须有结果,所谓结果包括:生成数据集,在结果窗口产生了表格(可以因为观测是0没有结果),产生了宏变量(select into的方法只要能获得多行宏变量就可以)。
举例说明,这样的代码sqlobs的结果永远为1,而不会产生正确结果:
proc sql noprint;
select * from sashelp.class;
quit;
因为即没有数据集产生(比如create table语句),也没有果窗口产生的表格(因为有noprint),也没有宏变量。
下面的代码,sqlobs的结果也是1:
proc sql noprint;
select age into:age from sashelp.class;
quit;
因为虽然产生了宏变量,但是这个宏变量的值只是第一行的值。如果要产生正确结果,只要用separated by就可以了,或者其他能获取多行的方法。
这个宏变量的原理应该是sas会记录扫描过得观测数,所以如果没有数据集,结果窗口的表格,或者宏变量,sas根本不会去扫描结果的观测,所以也就会返回一个1了事。
有意思的是如果你在定义宏变量时指定了个数,比如下面代码,这个宏变量的值就会是2:
proc sql noprint;
select age into:age1-:age2 from sashelp.class;
quit;
因为你只是指定了两个宏变量,所以SAS也就会扫描2行,而实际显然不是2个结果。
sysnobs:这个宏变量可以获取任何过程步结果。对于所有最后生成数据集的过程步,该宏变量获取的是最后生成数据集的观测数。如果没有生成数据集,那么他获取的是输入数据集的观测数。如果生成了数据集但没有观测,他的值是-1.
这个宏变量涉及到两个问题,第一个是当生成多个数据集的时候,他的值是哪个数据集的观测数。第二个是where和这个宏变量谁先执行的问题。
先说第一个,sysnobs永远是最后一个生成的数据集,尽管在一个过程部内,这个规则也是成立的。比如
data class1 class2;
set sashelp.class;
if age>12 then output class2;
output class1;
run;
%let n=;
%let n=&sysnobs.;
%put sysnobs=&n.;
结果为12。因为class2是后生成的,所以是以class2为准的。
再说第二个,比如以下两段代码,结果应该是多少呢?
代码1:
data _null_;
set sashelp.class(where=(age>12));
run;
或者
data _null_;
set sashelp.class;
where age>12;
run;
class本来有19条,其中满足大于12岁的有12条。如果是sysnobs先执行,那么结果应该是19,如果where先执行结果是12.
代码2:
data class(where=(age<=16));
set sashelp.class;
run;
这里是相同的问题,只不过一个是输入数据集,一个是输出数据集。如果sysnobs先执行,那应该是19条,如果where先执行,结果是12条。
经过测试,sysnobs永远是先于where执行的,所以以上的所有结果都是19条。
但是需要注意,下面的结果是12条:
data class;
set sashelp.class;
where age>12;
run;
因为where是对输入数据集的筛选,而最后的生成数据集并没有被where筛选。