Macros SAS和函数内部宏故障

Macros SAS和函数内部宏故障,macros,sas,sum,proc-sql,Macros,Sas,Sum,Proc Sql,我得到了所有的钱 我得到这个错误: 错误:函数SUM需要一个数值表达式作为参数1。 错误:函数SUM需要一个数值表达式作为参数2。 错误:函数SUM需要一个数值表达式作为参数3。 错误:在贡献表中未找到以下列:m1sales、m2sales、m3sales 错误:文件WORK.QTR1.DATA不存在。如果要引用在当前SELECT语句中派生的值,则需要将计算的关键字添加到查询中 data Month1; input Name $ sales; cards; Joyce 235 Marsha 35

我得到了所有的钱

我得到这个错误:

错误:函数SUM需要一个数值表达式作为参数1。 错误:函数SUM需要一个数值表达式作为参数2。 错误:函数SUM需要一个数值表达式作为参数3。 错误:在贡献表中未找到以下列:m1sales、m2sales、m3sales


错误:文件WORK.QTR1.DATA不存在。

如果要引用在当前SELECT语句中派生的值,则需要将
计算的
关键字添加到查询中

data Month1;
input Name $ sales;
cards;
Joyce 235
Marsha 352
Bill 491
Vernon 210
Sally 418
;
data Month2;
input Name $ sales;
cards;
Joyce 169
Marsha 281
Bill 315
Vernon 397
Sally 305
;
data Month3;
input Name $ sales;
cards;
Joyce 471
Marsha 314
Bill 394
Vernon 291
Sally 337
;
data Month4;
input Name $ sales;
cards;
Joyce 338
Marsha 259
Bill 310
Vernon 432
Sally 362
;
data Month5;
input Name $ sales;
cards;
Joyce 209
Marsha 355
Bill 302
Vernon 416
Sally 475
;
data Month6;
input Name $ sales;
cards;
Joyce 306
Marsha 472
Bill 351
Vernon 405
Sally 358
;

options sgen;
%let qtr=qtr1;
%Macro ProcSql;
    Proc Sql;
    %if &qtr=qtr1 %then %do;
        %let month1=month1;
        %let month2=month2;
        %let month3=month3;
    %end;
    %else %if &qtr=qtr2 %then %do;
        %let month1=month4;
        %let month2=month5;
        %let month3=month6;
    %end;
    %else %if &qtr=qtr3 %then %do;
        %let month1=month7;
        %let month2=month8;
        %let month3=month9;
    %end;
    %else %%if &qtr=qtr4 %then %do;
        %let month1=month10;
        %let month2=month11;
        %let month3=month12;
    %end;
    create table &qtr as
    select &month1.name, &month1.sales as m1sales, &month2.sales as m2sales,
            &month3.sales as m3sales, sum(m1sales, m2sales, m3sales) as 
qtrsales
        from &month1, &month2, &month3
        where &month1.name=&month2.name=&month3.name;
    select sum(m1sales) as m1total, sum(m2sales) as m2total, sum(m3sales) as 
m3total,
            sum(qtrsales) as qtrtotal
        from &qtr;
%mend ProcSql;
    %ProcSql;

尽早删除多个数据集。

我只是将数据连接到一个数据集中。在我的经验中,对于多个时间段(或其他变量)拥有多个相同的数据集是SAS最糟糕的反模式之一

create table &qtr as
  select &month1.name
       , &month1.sales as m1sales
       , &month2.sales as m2sales
       , &month3.sales as m3sales
       , sum(calculated m1sales,calculated m2sales,calculated m3sales) as qtrsales
   from &month1, &month2, &month3
   where &month1.name=&month2.name
     and &month1.name=&month3.name
;
使用一个数据集中的数据,操作起来就容易多了。您可以在SQL中轻松聚合它:

data sales;
 set month1 (in=m1) month2 (in=m2) month3 (in=m3) month4 (in=m4) month5 (in=m5)  month6 (in=m6);
 if m1 then month=1;
 if m2 then month=2;
 if m3 then month=3;
 if m4 then month=4;
 if m5 then month=5;
 if m6 then month=6;
 qtr = ceil(month/3);
run;
或将其制成表格:

proc sql;
 create table monthly_sales as
 select qtr,
        month,
        sum(sales) as monthly_sales
 from sales
 group by month ;

 create table quarterly_sales as
 select month,
        qtr,
        monthly_sales,
        sum(monthly_sales) as quarterly_sales
 from monthly_sales
 group by qtr;
quit;
或将其转置:

proc tabulate data=sales;
 var sales;
 class month qtr;
 table qtr*(month all='total')*sales=''*sum='';
run;
使用宏生成代码,而不是控制流

如果必须使用宏,请尝试在数据步骤中使用宏生成代码,而不是在多个数据集上循环。(宏应该用来生成代码,这就是它们的设计目的)。它们经常被滥用作为程序控制结构的代理,这通常会导致无法维护的混乱局面)

在这里,我使用宏生成用于连接月份的数据步骤,其中月份数是一个变量:

proc sort data=sales; by name;
proc transpose data=sales out=sales_wide;
 by name;
 var sales;
 id month;
run;

如果您使用
options mprint
可以看到生成的代码与上述代码相同。

您的代码将更易于理解和维护,如果您使用的数据集包含一个月变量,则无需使用宏。是的,谢谢。但我得到了这个数据集和一系列问题,你确定销售是一个数字变量吗?
%macro myset(months);
 set %do i=1 %to &months; month&i (in=m&i) %end;  ;
 %do i=1 %to &months; 
    if m&i then month=&i;
 %end;
%mend;

data sales;
 %myset(months=6);
 qtr = ceil(month/3);
run;