【问题标题】:Loop between dates在日期之间循环
【发布时间】:2018-04-28 11:15:54
【问题描述】:

我创建了下面的宏来生成一些基于日期宏的数据集。

%macro pull(date);

proc sql;

create table new&date as 

select * from acct

where date=&date.;

quit;

%mend;

所以如果我想为 20170101 20170201 20170301 20170401 20170501 创建数据集,我所能做的就是使用下面的宏

%macro pull(20170101)

%macro pull(20170201)

%macro pull(20170301)

%macro pull(20170401)

%macro pull(20170501)

我现在计划的是创建两个宏变量

%let begin=20170101;

%let end =20170501;

并使用循环创建基于开始和结束的数据集。是否有可能这样做。所以我想要做的是将开始日期和结束日期作为宏变量,并从 acct 数据集中提取开始日期和结束日期之间的记录,并为开始日期和结束日期之间的每个月创建单独的数据集

Note 数据集每年都有每月的日期。

下面是我正在尝试的代码

%let beg="01jan2000"d;
%let end="01jan2001"d; 
%macro Test;
%do date=&beg. %to &end.;
proc sql;
create table IPw_&date. as  
select *
from sample
where date=&date. quit;
%end;
%mend;
%Test;

【问题讨论】:

  • 你试过什么?你知道INTNX这样的区间函数吗?你知道 SAS 日期值和 SAS 日期格式吗?
  • 您真的需要单独的数据集吗?为什么不直接使用where date between &date1 and &date2
  • 您可能对 SAS 宏附录感兴趣,它有一个演示宏列表,其中显示了如何循环日期。请参阅此处的示例代码列表,其中包含完整的说明。 communities.sas.com/t5/SAS-Communities-Library/…

标签: sas


【解决方案1】:

当必须从非 SAS 日期值的值推断日期信息时,您将需要 input 信息以获取日期值,并 put 迭代值以获得所需的非日期表示。

本例演示

  • INPUTN 函数使用信息 YYMMDD8 将 YYYYMMDD 参数解析为日期值。
  • INTNX 函数计算日期值的月份的第一天
  • PUTN 函数使用格式 YYMMDDN8 将日期值转换为 YYYYMMDD 表示形式。
  • %DO %WHILE 语句用于迭代
  • INTNX 函数将迭代变量提前到下个月的开始

代码

%macro pull(yyyymmdd);
  %local out;

  %let out = pull_&yyyymmdd;

  data &out;
    pull_date = input ("&yyyymmdd", yymmdd8.);
    format pull_date yymmdd10.;
  run;
%mend;

%macro pull_each_month(begin=, end=);
  %local 
    begin_date end_date
    begin_month end_month
    pull_date pull_ymd
  ;

  %put NOTE: &=begin &=end;

  %let begin_date = %sysfunc(inputn(&begin,yymmdd8.));
  %let end_date   = %sysfunc(inputn(&end,yymmdd8.));

  %put NOTE: &=begin_date &=end_date;

  %let begin_month = %sysfunc(intnx(month,&begin_date,0));
  %let end_month   = %sysfunc(intnx(month,&end_date,0));

  %put NOTE: &=begin_month &=end_month;

  %let pull_month = &begin_month;
  %do %while (&pull_month <= &end_month);
    %let pull_ymd = %sysfunc(putn(&pull_month,yymmddn8.));
    %put NOTE: Invoking pull for &=pull_month &=pull_ymd;

    %pull (&pull_ymd)

    %let pull_month = %sysfunc(INTNX(MONTH,&pull_month,1));

  %end;
%mend;

%pull_each_month (
  begin = 20170101
, end   = 20170501
)

%macro pull_each_month(begin=, end=);
  %local 
    begin_date end_date
    begin_month end_month
    pull_date pull_ymd
  ;

  %put NOTE: &=begin &=end;

  %let begin_date = %sysfunc(inputn(&begin,yymmdd8.));
  %let end_date   = %sysfunc(inputn(&end,yymmdd8.));

  %put NOTE: &=begin_date &=end_date;

  %let begin_month = %sysfunc(intnx(month,&begin_date,0));
  %let end_month   = %sysfunc(intnx(month,&end_date,0));

  %put NOTE: &=begin_month &=end_month;

  %let pull_month = &begin_month;
  %do %while (&pull_month <= &end_month);
    %let pull_ymd = %sysfunc(putn(&pull_month,yymmddn8.));
    %put NOTE: Invoking pull for &=pull_month &=pull_ymd;
    %let pull_month = %sysfunc(INTNX(MONTH,&pull_month,1));
  %end;

%mend;

%pull_each_month (
  begin = 20170101
, end   = 20170501
)

【讨论】:

  • 谢谢理查德。但是我们有没有可能在不使用 %macro 和 %mend 的情况下做到这一点
  • 你不能在宏之外有宏逻辑(%do,%if)。
【解决方案2】:
%macro pull(begin,end);
%let i=0;
%let begin=%sysfunc(inputn(&begin,anydtdte9.));
%let end=%sysfunc(inputn(&end,anydtdte9.));
%do %until (&begin=&end);
    %let begin=%sysfunc(intnx(month,&begin,&i));
    %let date=%sysfunc(putn(&begin,yymmddn8.));
    proc sql;
    create table new&date as 
    select * from acct where date=&date.;
    quit;
    %let i=%eval(&i+1);
%end;
%mend;

%pull(20170101,20170501)

【讨论】:

  • 感谢陈提供的代码。但我不想使用 %macro 和 %mend。我想要的只是声明两个宏变量 %let beg="01jan2000"d; %let end="01jan2001"d;并使用这些值来生成数据集,而不是给它 %pull()
  • 所以我正在寻找的是,我不想通过 %pull(20170101,20170501) 手动输入日期。它需要从 %let 宏中选择
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多