【问题标题】:Conditiona a SAS Macro base on names in a list根据列表中的名称调整 SAS 宏
【发布时间】:2014-03-14 07:25:08
【问题描述】:

这里是新的。

我编写了一对宏来搜索我们工作中的一个数据库。这是我如何使用它的一个例子:

%LET SVlist=%str(R_PAR_SV_2012_VER3 R_PAR_SV);
%LET ovlist=%str(R_PAR_OV_2012_VER3 R_PAR_OV);




%LET FILTER=
(DIAGNOS like 'S72%' or diagnos contains ' S72' or
DIAGNOS like 'I21%' or diagnos contains ' I21'
);

%LET OVSELECT=PNR,
          PNRQ, 
          INDATUM, 
          OP, 
          DIAGNOS, 
          HDIA,
          alder,
          SJUKHUS;
%LET sVSELECT=&OVSELECT,UTDATUM,OPD1;

%macro ovsql(ovlist);
proc sql noprint;
%let n=%sysfunc(countw(&ovlist));
    %do i=1 %to &n;
        %let val = %scan(&ovlist,&i);


        create table work.&val as

            select &ovselect,
'SV' as souce
from r_par.&val
            where pnrq='0';


    %end;
quit;
%mend;

%macro svsql(svlist);
proc sql noprint;
%let n=%sysfunc(countw(&svlist));
    %do i=1 %to &n;
        %let val = %scan(&svlist,&i);


        create table work.&val as

            select &svselect,
'SV' as souce
from r_par.&val
            where pnrq='0';


    %end;
quit;
%mend;

%ovsql(&ovlist);
%svsql(&SVlist);

以上工作正常:

如您所见,我基本上有两个宏来处理 2 种略有不同的数据集。为此,我使用了两个列表:

我想知道是否有一种方法可以合并宏,以便当列表中的集合包含名称中的字母 OV 和 SV 时,您可以调节程序运行“OV 宏”列表中的集合包含字母 SV。这个可以吗?

这是我自己的尝试,我尝试了一些变体,但无法使其工作,以供参考。

options mprint;
%macro PSQL(list);
proc sql ;
%let n=%sysfunc(countw(&list));
    %do i=1 %to &n;
        %let val = %scan(&list,&i);
         %let g= 
%substr(&val,7,2);
         ;
        %put(&g);

         %if &g=:SV %then %do; 

        create table work._&val as

            select &svselect,
'SV' as souce
from r_par.&val
            where pnrq='0';
            %end;
            %else %if  &g=:OV %then %do ;
                    create table work._&val as

            select &ovselect,
'OV' as souce
from r_par.&val
            where pnrq='0';
    %end;
    %end;
quit;
%mend;

%PSQL(R_PAR_SV_2012_VER3 R_PAR_OV_2012_VER3);

我真的很乐意提供任何帮助。当谈到 sas 宏语言时,我有点新手。提前致谢

【问题讨论】:

  • 如果你打开OPTIONS MPRINT;,你会在日志中得到什么?您是否看到任何具体错误?

标签: sql macros sas


【解决方案1】:

我会写得有点不同。拥有两个%if 块并不能真正为你买那么多;它仍然在维护两段代码,其余代码不是很有趣或难以维护两次。

你可以用一段代码来写这个:

create table work._&val as
        select &&shortval.select, "&shortval." as source
          from r_par.&val
          where pnrq='0';

现在添加一些东西来将 &shortval 定义为 SV 或 OV,您现在根本不需要 %if 块。我认为您将 &g 用于此目的,如果这是其目的,请将其重命名为 shortval (因为 g 是宏变量的坏名称)并使用

进一步,对上述代码结构的一些一般性评论:

一般来说,这种方式的宏解析比其他方法更难达到相同的结果。虽然可以这样做,但与数据驱动的宏调用相比,它的工作量更大、更容易出错且更难维护。

不要让宏接受包含多次迭代的数据的单个参数,而是将宏编写为单个迭代宏,并以编程方式多次调用它。 IE,有一个数据集,每个数据集包含一行,变量“Type”:

R_PAR_SV_2012_VER3
R_PAR_OV_2012_VER3

然后做:

proc sql;
 select cats('%PSQL(',type,')') into :psqllist separated by ' '
        from have;
quit;

&psqllist.;

这使您可以更轻松地控制呼叫。它还允许您通过轻松包含几个宏变量来更轻松地实现上述部分。

这意味着,如果我写了上面的宏,我会这样做:

%macro psql(shortval=,val=);
  create table work._&val as
            select &&shortval.select, "&shortval." as source
              from r_par.&val
              where pnrq='0';
%mend psql;

proc sql;
 select cats('%PSQL(val=',type,',shortval=',substr(type,7,2),')') into :psqllist separated by ' '
        from have;
quit;
&psqllist.;

现在您有大约 10 行易于维护的代码和一个小型数据集,您甚至可以从 Excel 工作表或其他数据源中提取这些数据(取决于该值列表的来源)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 2015-08-06
    相关资源
    最近更新 更多