在SAS Proc Sql中进行动态SQL查询

时间:2013-07-12 21:27:04

标签: sql sas

这是一个反映了一些进展的编辑:

我有以下功能:

proc fcmp outlib=mydir;
 function sqlWhere(interval $, myDate $) $;
 ...
 return("id");
 endsub;
quit;

这是经过测试并且工作正常。所以我试过了:

%macro sqlWhere(interval, myDate);
  &interval.("year") AS t
  &myDate.("someDateField") AS tt
%mend;
proc sql;
  CREATE TABLE test AS (
    SELECT %sqlWhere(t, tt)
    FROM myTable);
quit;

当我运行选择时,顶部运行正常。然而,proc sql爆炸并说我错过了一个逗号。我很困惑,因为函数在其他测试中返回“id”,这应该使代码工作。该错误表示“tt”部分缺少逗号...

我正在尝试在SAS中进行动态查询。我有几个问题,我不确定我想做什么是可能的。另外,抱歉删除先前的问题;我想给出一个更好的解释。

说我有这段代码:

proc sql;
SELECT 
  YEAR(myDate) AS yr, 
  MONTH(myDate) AS mo,
  id
FROM
  myTable;
run;

我试图让它有条件。这给出了两个问题。首先,我无法使用基本语法。其次,我无法使用自定义函数来创建正确的字符串。

我想要这样的事情:

%let a = sqlDate("month");
proc sql;
SELECT
  &a
FROM
  myTable;
run;

这种结构不起作用,即使我放弃了这个功能,只需输入

即可
%let a = "YEAR(myDate) AS yr, MONTH(myMonth) AS mo, id";

这样的事情可能吗?

我的第二个问题是如何构建函数本身,但我想确认我甚至可以先做这样的事情。我基本上把一个指标放在一个主程序中,它是“day”,“week”,“month”或“year”,然后告诉程序以给定的方式查询SQL。我可以通过整个字符串吗?是否有可能以这种方式基于输入构建字符串?

1 个答案:

答案 0 :(得分:4)

您对第一个问题的解释是对SAS宏的误解。 当你提出这个:

%let a = "YEAR(myDate) AS yr, MONTH(myMonth) AS mo, id";

SAS会在您的查询中加入:

"YEAR(myDate) AS yr, MONTH(myMonth) AS mo, id"

即:它会保留报价。如果你想把它放在一个SAS宏变量中来“隐藏”类似函数的东西,你必须使用%str()函数而不是“或”。 所以,如果你愿意写:

%str(YEAR(myDate) AS yr, MONTH(myMonth) AS mo, id);

你会有一些有用的东西。

回答你的第二个问题:这当然是可能的。但请记住一些非常重要的事情:在SAS代码运行之前,会解释并替换任何宏函数,宏变量定义或对开放代码中的宏变量的调用。 如果您的宏变量/函数取决于SAS数据步骤或proc的结果,则需要将其封装在宏函数中:其中的所有内容仅在运行时进行解释和替换。

修改的 回答你的评论:主要是我传递的一般建议,因为你似乎不熟悉SAS Macro。在某些情况下,你可以得到奇怪的结果,看起来你的宏变量没有设置/更改,如果你不知道它,它可能会令人沮丧。 (我们都是第一次遇到它;))

在您的特定情况下,如果我们假设您已经创建了一个返回相应选择部分的sqldate宏,那么您可能最好立即将其放入查询中。 e.g:

%macro sqldate(period);
    &period.(mydate) as period
%mend;
/*note no semicolon, since a macro function is basically the same as saying: resolve this piece of macro code and add the result directly to my written code.*/

proc sql;
    select %sqldate(month)
    from mytable;
quit;
/*also note: you end proc sql with a quit statement instead of run*/