我使用PROC SQL进行Oracle数据库查询(虽然我不是数据库人员,所以我不能比这更具体),我们经常应用自动加载的库中的格式。我想知道是否有更快的方式来编程这些类型的查询,例如,让我说在视图中我有一个名为prim_disease_cd的变量,我想把它拉出来,应用格式(具有同名)并称之为prim_disease_cd。现在我会做
put(a.prim_disease_cd, prim_disease_cd.) as prim_disease_cd
有没有办法可以使用宏语言来缩短它?到目前为止,我一直没有成功,但我们经常这样做,看起来效率很低。基本上我想要一个宏,它接受一个视图/数据集a和一个变量X并将" put(a.X,X。)应用为X"
此外,无论如何,如果有的话,我可以为日期实施这样的事情,那将是很好的,即替换
datepart(a.(var_name)) as (var_name) format mmddyy10.
感谢您提供的任何帮助。
答案 0 :(得分:1)
您可以创建简单的宏来执行这两项操作。仅发出类似语句的一部分的宏通常称为宏函数或函数样式宏。确保不要发出任何分号。例如,您可以制作这两个宏。
%macro decode(alias);
%local varname ;
%let varname=%scan(&alias,-1,.);
put(&alias,&varname..) as &varname
%mend;
%macro datepart(alias);
%local varname ;
%let varname=%scan(&alias,-1,.);
datepart(&alias) as &varname format yymmdd10.
%mend;
然后您的SQL查询可能如下所示:
create table want as
select a.patid
, %decode(a.prim_disease_cd)
, %datepart(a.onset_date)
from oralib.diagnosis a
;
您可能会发现使用这些将使您的SAS代码更难维护。可能更容易找到一种方法来自动生成编辑器中的文本。或运行一个程序,从元数据生成文本,然后将其复制并粘贴到您的程序中。
PS不要将MDY(或DMY)格式用于日期。这会让你的欧洲(或美国)朋友感到困惑。
答案 1 :(得分:0)
如果需要在针对Oracle数据的未来查询中使用<concept>_cd
代码值,我会说创建一个新变量,例如<concept>_value
或<concept>
。
如果Oracle查询中的编码数据一致地命名,例如仅<concept>_cd
,则可以让宏检查提取的数据并创建SAS视图,该视图通过SAS格式应用从代码到值的映射。由于您从Oracle中提取编码值,因此Oracle中可能有一个或多个查找表将代码映射到值,并且可能您的SAS格式是根据该数据构建的。
在您的用例中,将代码转换为值实质上是对假定的查找表执行左连接。我假设您正在执行代码映射,以便更容易执行子集选择。
如果您只报告数据,则可能只需要将格式应用于代码变量本身。下面是一个示例宏,它根据命名约定<concept>_cd
data code_lookups;
length id 8 fmt $31 desc $50 ;
input id & fmt & desc;
datalines;
1 country_cd US
2 country_cd Canada
10 color_cd Green
11 color_cd Blue
12 color_cd Red
20 footwear_cd Shoes
21 footwear_cd Socks
22 footwear_cd Laces
run;
proc format cntlin=code_lookups(rename=(fmt=fmtname id=start desc=label));
run;
data have(label="Some result from Oracle with unmapped codes");
input item_id country_cd color_cd footwear_cd;
datalines;
1 1 11 22
2 2 11 21
3 1 12 22
3 1 10 20
run;
%macro auto_codemap (data=, out=, out_struct=view, map_func=new_var);
%local dsid i l p q varname;
%let dsid = %sysfunc(open(&data));
%if &map_func ne format_only and &map_func ne new_var %then %do;
%put ERROR: &=map_func unknown.;
%end;
proc sql;
create &out_struct &out as
select
%do i = 1 %to %sysfunc(attrn(&dsid,nvar));
%if &i > 1 %then %str(,);
%let varname = %sysfunc(varname(&dsid,&i));
&varname
%let l = %length(&varname);
%if &l > 3 %then %do;
%let p = %eval(&l-3);
%let q = %eval(&l-2);
%if %substr(%upcase(&varname),&q) = _CD %then %do;
%if &map_func = format_only %then %do;
format=%str(&varname).
%end;
%else %if &map_func = new_var %then %do;
, put(&varname, %str(&varname).) as %substr(&varname,1,&p)
%end;
%end;
%end;
%end;
from &data
;
quit;
%let dsid = %sysfunc(close(&dsid));
%mend;
options mprint;
%auto_codemap (data=have, out=want)
proc print data=want;
run;
%auto_codemap (data=have, out=want2, map_func=format_only)
proc print data=want2;
run;