sql - SAS/SQL - 使用自定义函数创建 SELECT 语句

标签 sql sas

更新

鉴于这种使用 INTNX 的新方法,我认为我可以使用循环来进一步简化事情。如果我制作一个数组怎么办:

data;
    array period [4] $ var1-var4 ('day' 'week' 'month' 'year');
run;

然后尝试为每个元素创建一个循环:

%MACRO sqlloop;
  proc sql;
    %DO k = 1 %TO dim(period);  /* in case i decide to drop something from array later */
      %LET bucket = &period(k)
      CREATE TABLE output.t_&bucket AS (
        SELECT INTX( "&bucket.", date_field, O, 'E') AS test FROM table);
    %END
  quit;
%MEND
%sqlloop

这不太行,但它捕获了我想要的想法。它可以只对 INTX 中的每个值运行查询。这有意义吗?


我有几个先前的问题正在合并为一个。我从其他人那里得到了一些非常有用的建议,希望这可以将它们联系在一起。

我有以下函数创建一个动态字符串来填充 SAS proc sql; 代码块中的 SELECT 语句:

proc fcmp outlib = output.funcs.test;
    function sqlSelectByDateRange(interval $, date_field $) $;
        day = date_field||" AS day, ";
        week = "WEEK("||date_field||") AS week, ";
        month = "MONTH("||date_field||") AS month, ";
        year = "YEAR("||date_field||") AS year, ";

        IF interval = "week" THEN
            do;
                day = '';
            end;
        IF interval = "month" THEN
            do;
                day = '';
                week = '';
            end;
        IF interval = "year" THEN
            do;
                day = '';
                week = '';
                month = '';
            end;
        where_string = day||week||month||year;
    return(where_string);
    endsub;
quit;

我已经验证这会创建我想要的字符串类型:

data _null_;
    q = sqlSelectByDateRange('month', 'myDateColumn');
    put q =;
run;

这会产生:

q=MONTH(myDateColumn) AS month, YEAR(myDateColumn) AS year,

这正是我想要的 SQL 字符串。根据之前的问题,我认为我需要在 MACRO 中调用此函数。然后我想要这样的东西:

%MACRO sqlSelectByDateRange(interval, date_field);
  /* Code I can't figure out */
%MEND

PROC SQL;
  CREATE TABLE output.t AS (
    SELECT 
      %sqlSelectByDateRange('month', 'myDateColumn')
    FROM
      output.myTable
  );
QUIT;

我无法理解如何让代码调用此宏并将其解释为 SQL SELECT 字符串的一部分。我已经在其他答案中尝试了一些前面的例子,但我就是无法让它发挥作用。我希望这个更具体的问题可以帮助我填补这个缺失的步骤,以便我将来可以学习如何做。

最佳答案

两件事:

首先,您应该能够使用 %SYSFUNC调用您的自定义函数。

%MACRO sqlSelectByDateRange(interval, date_field);
    %SYSFUNC( sqlSelectByDateRange(&interval., &date_field.) )
%MEND;

请注意,通过 SYSFUNC 调用函数时不应使用引号。另外,you cannot use SYSFUNC with FCMP functions until SAS 9.2 .如果您使用的是早期版本,这将不起作用。

其次,您的 select 子句中有一个尾随逗号。您可能需要一个虚拟列,如下所示:

PROC SQL;
  CREATE TABLE output.t AS (
    SELECT 
      %sqlSelectByDateRange('month', 'myDateColumn')
      0 AS dummy
    FROM
      output.myTable
  );
QUIT;

(注意 dummy 之前没有逗号,因为逗号已经嵌入到您的宏中。)


更新

我阅读了您对另一个答案的评论:

I also need to be able to do it for different date ranges and on a very ad-hoc basis, so it's something where I want to say "by month from june to december" or "weekly for two years" etc when someone makes a request.

我想我可以推荐一种更简单的方法来完成您正在做的事情。首先,我将创建一个包含日期和值的非常简单的数据集。日期分布在不同的日、周、月和年中:

DATA Work.Accounts;

    Format      Opened      yymmdd10.
                Value       dollar14.2
                ;

    INPUT       Opened      yymmdd10.
                Value       dollar14.2
                ;

DATALINES;
2012-12-31  $90,000.00
2013-01-01 $100,000.00
2013-01-02 $200,000.00
2013-01-03 $150,000.00
2013-01-15 $250,000.00
2013-02-10 $120,000.00
2013-02-14 $230,000.00
2013-03-01 $900,000.00
RUN;

您现在可以使用 INTNX 函数创建第三列以将“Opened”列四舍五入到某个时间段,例如 'WEEK''MONTH',或 'YEAR'(参见 complete list):

%LET Period = YEAR;

PROC SQL NOPRINT;

    CREATE TABLE Work.PeriodSummary AS
    SELECT   INTNX( "&Period.", Opened, 0, 'E' ) AS Period_End FORMAT=yymmdd10.
           , SUM( Value )                        AS TotalValue FORMAT=dollar14.
    FROM     Work.Accounts
    GROUP BY Period_End
    ;

QUIT;

WEEK 的输出:

Period_End   TotalValue
2013-01-05     $540,000
2013-01-19     $250,000
2013-02-16     $350,000
2013-03-02     $900,000

MONTH 的输出:

Period_End   TotalValue
2012-12-31      $90,000
2013-01-31     $700,000
2013-02-28     $350,000
2013-03-31     $900,000

YEAR 的输出:

Period_End   TotalValue
2012-12-31      $90,000
2013-12-31   $1,950,000

关于sql - SAS/SQL - 使用自定义函数创建 SELECT 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17658864/

相关文章:

c# - 使用 ASP.net 执行 INSERT 命令

sql - 尝试在 ubuntu 中使用 RODBC 连接到 ODBC 服务器

sas - 如何删除特殊 ASCII 字符?

MYSQL - 无法正确加入 Group By 2 Columns

Mysql:连接创建 View 重复行4次

sas - 在企业指南中,如何重新打开以前的数据步骤输出来查看它?

javascript - SAS、PHP 或 JavaScript 中的梅登黑德网格平方函数

csv - SAS:堆叠具有空白观察值的 CSV 文件

sql - Sequelize js获取关联模型的计数

exchange-server - Exchange Server 和 SAS 9.1.3/9.2