3

我有一张按类别(数字)排列的帖子的表格。我得到了一个表,每个列的名称为 _number,例如 _16、_881、_853 等(它们不按顺序排列)。

我需要在 proc sql 中对所有这些进行求和,但我不想在数据步骤中创建变量,也不想写所有列名。我试过这个但不起作用:

proc sql;
select sum(_815-_16) as nnl
from craw.xxxx;
quit;

我尝试从第一个数字到最后一个数字,也从第一个数字对应的数字到最后一个数字。给我一个不正确的数字。

有任何想法吗?

谢谢!

4

2 回答 2

2

你不能在 SQL 中使用变量列表,所以_:andvar1-var6var1--var8不工作。

最简单的方法是数据步骤视图。

proc sort data=sashelp.class out=class;
 by sex;
run;
*Make transposed dataset with similar looking names;
proc transpose data=class out=transposed;
 by sex;
 id height;
 var height;
run;
*Make view;
data transpose_forsql/view=transpose_forsql;
 set transposed;
 sumvar = sum(of _:);  *I confirmed this does not include _N_ for some reason - not sure why!;
run;

proc sql;
 select sum(sumvar) from transpose_Forsql;
quit;
于 2014-07-28T15:11:03.807 回答
1

我没有文档支持这一点,但根据我的经验,我相信 SAS 会假设sum()SQL 中的任何语句都是 sql-aggregate 语句,除非它有理由不相信。

我可以看到 SAS 区分两者的唯一方法是通过参数传递给它的方式。在下面的示例中,您可以看到内部sum()函数有 3 个参数传入,因此 SAS 会将其视为 SASsum()函数(因为 sql-aggregate 语句只允许单个参数)。然后将 SAS 函数的结果作为单个参数传递给 sql-aggregate sum 函数:

proc sql noprint;
  create table test as 
  select sex,
         sum(sum(height,weight,0)) as sum_height_and_weight
  from sashelp.class
  group by 1
  ;
quit;

结果:

proc print data=test;
run;

              sum_height_
Obs    Sex     and_weight

 1      F        1356.3
 2      M        1728.6

另请注意我在代码中通过传入0SAS 函数使用的技巧 - 这是添加附加参数而不更改预期结果的简单方法。根据您的数据,您可能希望将 替换0为空值(即.)。

编辑:要解决未知列名的问题,您可以创建一个宏变量,其中包含要汇总在一起的列名列表:

proc sql noprint;
  select name into :varlist separated by ',' 
  from sashelp.vcolumn 
  where libname='SASHELP'
    and memname='CLASS'
    and upcase(name) like '%T'  /* MATCHES HEIGHT AND WEIGHT */
    ;
quit;

%put &varlist;

结果:

Height,Weight

请注意,您需要更改上述通配符以匹配您的场景 - 即。匹配以下划线开头的字段,而不是以字母 T 结尾的字段。因此您的最终 SQL 语句将如下所示:

proc sql noprint;
  create table test as 
  select sex,
         sum(sum(&varlist,0)) as sum_of_fields_ending_with_t
  from sashelp.class
  group by 1
  ;
quit;

这为乔的回答提供了另一种方法——尽管我相信按照他的建议使用视图是一种更清洁的方法。

于 2014-07-28T16:22:29.923 回答