Proc SQL分配缺失值

时间:2017-04-04 16:39:02

标签: sas proc-sql

如果我运行一个产生零行的查询,我仍然希望创建一个SAS数据集,其中一行包含所有已分配缺失值的列。

我找到了一种方法,可以使用单独的数据步骤:

%let dsid   = %sysfunc (open(myfile));
%let anyobs = %sysfunc (attrn(&dsid,ANY));
%let dsid   = %sysfunc (close(&dsid));
data _null_;
  if &anyobs=0 then do;
     call execute('data work.myfile; call missing(col1, col2, col3); run;');
end;

这很好但我想知道是否有办法为proc sql中的每一列分配缺失?

由于 丹

2 个答案:

答案 0 :(得分:3)

所以让我们说你执行这个:

proc sql;
  create table class as 
    select * from sashelp.class 
    where age=19;
quit;

然后你可以这样做:

%macro ifMissingRow(data=);
  %let dsid   = %sysfunc (open(&data.));
  %let anyobs = %sysfunc (attrn(&dsid,ANY));
  %let dsid   = %sysfunc (close(&dsid));
  %if &anyobs=0 %then %do;
    data &data.;
      output;
      set &data.;
    run;
  %end;
%mend ifmissingRow;

%ifMissingRow(data=class);

输出在设置之前,以便在SET停止数据步骤之前获取行,其中0行(h / t Tom为指针)。

答案 1 :(得分:3)

这是一种使用NOBS=语句的SET选项的简单方法,可确保您的数据集至少有一个观察值。

data want ;
  if 0=_nobs then output;
  set want nobs=_nobs;
run;

请注意,如果数据集很大并且您不想重新编写数据,那么您可能会使用某种方法来有条件地生成数据步骤。例如,您可以测试自动宏变量SQLOBS,如果它是0则生成数据步骤。在这种情况下,你不需要测试nobs。您也可以使用自动宏变量SYSLAST,而不是硬编码数据集名称。您可以使用CALL EXECUTE,但您也可以使用IFC()函数。

%sysfunc(dequote(
 %sysfunc(ifc(0=&sqlobs,'data &syslast;output;set &syslast;run;',''))
))

或许最好使用MODIFY语句并有条件地运行OUTPUT语句。您可以测试SQLOBS宏变量。

data &syslast ;
  if &sqlobs=0 then output;
  modify &syslast ;
  stop;
run;

或者您可以使用NOBS=选项MODIFY语句。

data &syslast ;
  if 0=_nobs then output;
  modify &syslast nobs=_nobs;
  stop;
run;

所有SQL解决方案

如果你知道至少一个变量名,那么你可以使用和SQL insert语句。

insert into &syslast (varname) values (null);

因此,您可以制作一个简单的宏,将数据集名称,观察数量和变量名称作为输入。

%macro ifzeronull(dsn,nobs,avar);
%if &nobs=0 %then %do;
  insert into &dsn (&avar) values (null);
%end;
%mend ;

然后你可以保持相同的PROC SQL调用并有条件地添加观察。

proc sql;
  create table want as
    select * from sashelp.class
    where age=19
  ;
  %ifzeronull(&syslast,&sqlobs,name)
quit;