【问题标题】:Making Dynamic SQL Queries in SAS Proc Sql在 SAS Proc Sql 中进行动态 SQL 查询
【发布时间】:2013-07-12 21:27:04
【问题描述】:

以下是反映所取得进展的修改:

我有以下有效的功能:

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";

这样的事情可能吗?

我的第二个问题是如何构造函数本身,但我想确认我什至可以先做这样的事情。我基本上是在主程序中放置一个指标,它可以是“日”、“周”、“月”或“年”,然后告诉程序以给定的方式查询 SQL。我可以以某种方式传递整个字符串吗?是否可以以这种方式根据输入构建字符串?

【问题讨论】:

  • 您确实忽略了此行末尾宏中的逗号: &interval.("year") AS t 在 sql 选择中,您需要用逗号分隔您选择的不同内容,但变量 t 的部分和变量 tt 的部分之间没有。 (放在不同的行不会让你不必放置逗号。;))
  • 我发现这个对宏变量和宏的解释非常有用:“SAS® Macros Are Just Text Substitution!” ... ARRRRGGGHHH!!!
  • 嘿伙计们,我只是无法让它与该功能一起使用。这些都是很好的信息,但我将提出一个更具体的新问题,看看是否可以缩小我做错的范围。

标签: sql sas


【解决方案1】:

您的第一个问题是对 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 数据步骤或过程的结果的宏变量/函数,则需要将其封装在宏函数中:其中的所有内容仅在运行时被解释和替换。

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

在您的特定情况下,如果我们假设您已经使SQLDate宏返回相应的选择部分,您可能最好将其立即放入查询中。例如:

%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*/

【讨论】:

  • 好的,我按照你在 %STR 上的说法,但我对宏函数封装有点困惑。在我的示例中,假设 sqlDate("Month") 返回我想要的字符串,我如何封装该值以便查询可以在运行时解释它?
  • 我想出了如何使该功能正常工作,只需将其集成到查询中,我就会看到您引用的问题! :)
  • 嗨@JeffreyKramer 我更新了我的回复,试图回答你的其他cmets。如果还不清楚,或者如果你最终得到意想不到的结果,我建议将你的新尝试添加为你的帖子的编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-01
  • 2013-07-08
相关资源
最近更新 更多