sas proc sql-获取最小日期并添加1年

sas proc sql-获取最小日期并添加1年,sas,proc-sql,Sas,Proc Sql,我有一个ID为的数据集,每个ID都有多个日期(实际上是datetime)。我想使用procsql来获取最短的日期时间,并将最短的日期时间增加1年。我试图在一个procsql中完成这一切,但一直在摸索,无法让它工作。下面是两次尝试。如有任何建议,我将不胜感激 *** GENERATE RANDOM DATES AFTER JAN 1, 2012 AND CREATE DATE/TIME VARIABLE ***; data have ; format date mmddyy10. dt

我有一个ID为的数据集,每个ID都有多个日期(实际上是datetime)。我想使用procsql来获取最短的日期时间,并将最短的日期时间增加1年。我试图在一个procsql中完成这一切,但一直在摸索,无法让它工作。下面是两次尝试。如有任何建议,我将不胜感激

*** GENERATE RANDOM DATES AFTER JAN 1, 2012 AND CREATE DATE/TIME VARIABLE ***;
data have ;
    format date mmddyy10.  dt datetime15.;
    do person_id=100, 200, 300, 400, 500;
    do i = 1 to 100;
        jdate = int(1000 * ranuni(123987));
        date = mdy(1,1,2012) + jdate;
        dt = dhms(date, 0,0,0);
        output;
    end;
    end;
run;

*** TRY1: THIS DOES NOT WORK - GETS MIN DATE/TIME AND REMERGES WITH EVERY RECORD***;
proc sql;
    create table try1 as
    select min(dt) as index_dt  format=datetime15. ,
        (dt + 365*24*60*60) as followup_date  format=datetime15.  
    from have
;
quit;


*** TRY2: USE MIN() IN "HAVING" STATEMENT ***;
*** PROBLEMATIC IF PERSON_ID HAS MIN(DT) OCCUR MULTIPLE TIMES ***;
proc sql;
    create table try2 as
    select person_id,
        dt as index_dt format=datetime15.,  
        (dt + 365*24*60*60) as followup_date  format=datetime15.  
    from have
    group by person_id
    having dt=min(dt) 
;
quit;

尝试使用“选择不同的人员id”而不是“选择人员id”-这将有助于解决您的重复问题。我不确定SAS是否将365*24*3600视为每年正确的秒数,因此这可能也是一个影响因素。

尝试使用“选择不同的人员id”而不是“选择人员id”-这将有助于解决您的重复问题。我不确定SAS是否将365*24*3600视为每年正确的秒数,因此这也可能是一个促成因素。

我认为您不能仅使用proc sql。我认为这样做:

*** GENERATE RANDOM DATES AFTER JAN 1, 2012 AND CREATE DATE/TIME VARIABLE ***;
data have ;
format date mmddyy10.  dt datetime15.;
do person_id=100, 200, 300, 400, 500;
do i = 1 to 100;
    jdate = int(1000 * ranuni(123987));
    date = mdy(1,1,2012) + jdate;
    dt = dhms(date, 0,0,0);
    output;
end;
end; 
run;

%macro do_elaboration(ds=);
/*count how many rows has my table */
%let dataset=&ds.;
%let DSID = %sysfunc(open(&dataset., IS));
%let nobs = %sysfunc(attrn(&DSID., NLOBS));
%let rc=%sysfunc(close(&DSID.));
/*loop over the number of rows*/
%do i=1 %to &nobs.;
    /*at each loop get one id*/
    data _NULL_;
       set &ds. (OBS=&i OBS=&i);
       call symputx("id", person_id);
    run;  
    /*with proc sql get the min_dt*/
    proc sql noprint;
       select min(dt) into:min_dt
       from &ds.
       where person_id=&id.
    ;
    quit;
    /*increment the min_dt with the function sas intnx*/
    data have_final_tmp;
        person_id = &id.;
        followup_date = intnx('dtyear',&min_dt,1);
        format followup_date datetime15.;
    run;
    /*put all id with the followup_date in only one dataset*/
    proc append base=have_final data=have_final_tmp force; 
    run;
%end;
%mend do_elaboration;
/*call the macro*/
%do_elaboration(ds=have);

我写代码很快,我没有测试它,所以你应该检查它,但概念很清楚。

我认为你不能只在proc-sql中完成。我认为这样做:

*** GENERATE RANDOM DATES AFTER JAN 1, 2012 AND CREATE DATE/TIME VARIABLE ***;
data have ;
format date mmddyy10.  dt datetime15.;
do person_id=100, 200, 300, 400, 500;
do i = 1 to 100;
    jdate = int(1000 * ranuni(123987));
    date = mdy(1,1,2012) + jdate;
    dt = dhms(date, 0,0,0);
    output;
end;
end; 
run;

%macro do_elaboration(ds=);
/*count how many rows has my table */
%let dataset=&ds.;
%let DSID = %sysfunc(open(&dataset., IS));
%let nobs = %sysfunc(attrn(&DSID., NLOBS));
%let rc=%sysfunc(close(&DSID.));
/*loop over the number of rows*/
%do i=1 %to &nobs.;
    /*at each loop get one id*/
    data _NULL_;
       set &ds. (OBS=&i OBS=&i);
       call symputx("id", person_id);
    run;  
    /*with proc sql get the min_dt*/
    proc sql noprint;
       select min(dt) into:min_dt
       from &ds.
       where person_id=&id.
    ;
    quit;
    /*increment the min_dt with the function sas intnx*/
    data have_final_tmp;
        person_id = &id.;
        followup_date = intnx('dtyear',&min_dt,1);
        format followup_date datetime15.;
    run;
    /*put all id with the followup_date in only one dataset*/
    proc append base=have_final data=have_final_tmp force; 
    run;
%end;
%mend do_elaboration;
/*call the macro*/
%do_elaboration(ds=have);
我写代码很快,不进行测试,所以你应该检查一下,但概念很清楚。

试试这个:

proc sql;
create table try1 as
select 
 min(dt) as index_dt  format=datetime15. ,
 calculated index_dt + 365*24*60*60 as followup_date format=datetime15.
from have
;
quit;
这里的技巧是使用“计算”关键字

此外,您可能需要执行以下操作以在上添加年份,而不是乘法:

proc sql;
create table try1 as
select 
 min(dt) as index_dt  format=datetime15. ,
 input(compress(
  put(intnx('YEAR', datepart(calculated index_dt),1,'SAMEDAY'),date9.)||":"||
  put(timepart(calculated index_dt),time5.)),datetime15.) as followup_date format=datetime15.
from have
;
quit;
试试这个:

proc sql;
create table try1 as
select 
 min(dt) as index_dt  format=datetime15. ,
 calculated index_dt + 365*24*60*60 as followup_date format=datetime15.
from have
;
quit;
这里的技巧是使用“计算”关键字

此外,您可能需要执行以下操作以在上添加年份,而不是乘法:

proc sql;
create table try1 as
select 
 min(dt) as index_dt  format=datetime15. ,
 input(compress(
  put(intnx('YEAR', datepart(calculated index_dt),1,'SAMEDAY'),date9.)||":"||
  put(timepart(calculated index_dt),time5.)),datetime15.) as followup_date format=datetime15.
from have
;
quit;
谢谢-我需要的是“经过计算”的声明!第二,感谢INTNX代码增加了一年。谢谢-我需要的是“计算”语句!再次感谢INTNX代码增加了一年。