SAS PROC SQL 组的第一个值
SAS PROC SQL first value by group
我有这样的数据集:
DATA try;
INPUT month :DATE9. account_id mob;
FORMAT month DATE9.;
DATALINES;
01JAN2004 11 9
01FEB2004 11 10
01MAR2004 11 11
01JUN2008 11 0
01JAN2005 12 -1
01FEB2005 12 -1
01MAR2005 12 0
01APR2005 12 1
01MAY2005 12 2
01JUN2005 12 3
01DEC2006 12 0
;
RUN;
我想为第一个(按account_id排序的帐户创建一个变量origination_date
,例如最小month - mob
日期月)mob
高于 0 和最小值 month
其中 mob=0
对于第一个 mob
小于或等于 0 的帐户.
因此,预期输出将是:
DATA output;
INPUT month :DATE9. account_id mob origination_date :DATE9.;
FORMAT month DATE9. origination_date DATE9.;
DATALINES;
01JAN2004 11 9 01APR2003
01FEB2004 11 10 01APR2003
01MAR2004 11 11 01APR2003
01JUN2008 11 0 01APR2003
01JAN2005 12 -1 01MAR2005
01FEB2005 12 -1 01MAR2005
01MAR2005 12 0 01MAR2005
01APR2005 12 1 01MAR2005
01MAY2005 12 2 01MAR2005
01JUN2005 12 3 01MAR2005
01DEC2006 12 0 01MAR2005
;
RUN;
到目前为止我有这个代码:
proc sql;
create table wanted as
select a.*,
coalesce( min(case when a.mob = 0 then a.month else . end),
min(intnx('month', a.month, -a.mob)) ) as origination_date format date9.
from try a
group by account_id
order by account_id, month;
quit;
但这不适用于 account_id = 11 的帐户,因为我不知道如何在 first mob
上添加条件:first mob
低于或等于零。你知道我怎样才能在 proc sql
内实现这个目标吗?基本上,我只想更改代码,使 min(case when a.mob = 0 then a.month else . end)
仅适用于第一个 mob
小于或等于零的帐户。
我不知道如何在数据步骤中没有 first.
和 last.
变量的情况下一步完成。可能在某些数据库中你可以做到这一点(使用 Passthrough)。
我认为使用 sas 应该分两步完成:
1) 根据条件为每个观察值计算 origination_date
。
2) 使用 proc sql
.
聚合变量
data want1;
set try;
format origination_date date9.;
by account_id month;
retain flag origination_date;
/*flag var description: 1-higher then 0, -1-less or equal 0*/
if first.account_id then do;
if mob > 0 then flag=1; else flag=-1;
origination_date="31DEC9999"d;
end;
if flag=1 then do;
if origination_date > intnx('month',month,-mob) then
origination_date=intnx('month',month,-mob);
end;
else do;
if flag = -1 and mob=0 then do;
if origination_date > month then
origination_date=month;
end;
end;
run;
proc sql;
create table want2 as
select account_id,month,mob,min(origination_date)as origination_date format=date9.
from want1
group by account_id
order by account_id,month;
quit;
输出:
+------------+-----------+-----+------------------+
| account_id | month | mob | origination_date |
+------------+-----------+-----+------------------+
| 11 | 01JAN2004 | 9 | 01APR2003 |
| 11 | 01FEB2004 | 10 | 01APR2003 |
| 11 | 01MAR2004 | 11 | 01APR2003 |
| 11 | 01JUN2008 | 0 | 01APR2003 |
| 12 | 01JAN2005 | -1 | 01MAR2005 |
| 12 | 01FEB2005 | -1 | 01MAR2005 |
| 12 | 01MAR2005 | 0 | 01MAR2005 |
| 12 | 01APR2005 | 1 | 01MAR2005 |
| 12 | 01MAY2005 | 2 | 01MAR2005 |
| 12 | 01JUN2005 | 3 | 01MAR2005 |
| 12 | 01DEC2006 | 0 | 01MAR2005 |
+------------+-----------+-----+------------------+
我有这样的数据集:
DATA try;
INPUT month :DATE9. account_id mob;
FORMAT month DATE9.;
DATALINES;
01JAN2004 11 9
01FEB2004 11 10
01MAR2004 11 11
01JUN2008 11 0
01JAN2005 12 -1
01FEB2005 12 -1
01MAR2005 12 0
01APR2005 12 1
01MAY2005 12 2
01JUN2005 12 3
01DEC2006 12 0
;
RUN;
我想为第一个(按account_id排序的帐户创建一个变量origination_date
,例如最小month - mob
日期月)mob
高于 0 和最小值 month
其中 mob=0
对于第一个 mob
小于或等于 0 的帐户.
因此,预期输出将是:
DATA output;
INPUT month :DATE9. account_id mob origination_date :DATE9.;
FORMAT month DATE9. origination_date DATE9.;
DATALINES;
01JAN2004 11 9 01APR2003
01FEB2004 11 10 01APR2003
01MAR2004 11 11 01APR2003
01JUN2008 11 0 01APR2003
01JAN2005 12 -1 01MAR2005
01FEB2005 12 -1 01MAR2005
01MAR2005 12 0 01MAR2005
01APR2005 12 1 01MAR2005
01MAY2005 12 2 01MAR2005
01JUN2005 12 3 01MAR2005
01DEC2006 12 0 01MAR2005
;
RUN;
到目前为止我有这个代码:
proc sql;
create table wanted as
select a.*,
coalesce( min(case when a.mob = 0 then a.month else . end),
min(intnx('month', a.month, -a.mob)) ) as origination_date format date9.
from try a
group by account_id
order by account_id, month;
quit;
但这不适用于 account_id = 11 的帐户,因为我不知道如何在 first mob
上添加条件:first mob
低于或等于零。你知道我怎样才能在 proc sql
内实现这个目标吗?基本上,我只想更改代码,使 min(case when a.mob = 0 then a.month else . end)
仅适用于第一个 mob
小于或等于零的帐户。
我不知道如何在数据步骤中没有 first.
和 last.
变量的情况下一步完成。可能在某些数据库中你可以做到这一点(使用 Passthrough)。
我认为使用 sas 应该分两步完成:
1) 根据条件为每个观察值计算 origination_date
。
2) 使用 proc sql
.
data want1;
set try;
format origination_date date9.;
by account_id month;
retain flag origination_date;
/*flag var description: 1-higher then 0, -1-less or equal 0*/
if first.account_id then do;
if mob > 0 then flag=1; else flag=-1;
origination_date="31DEC9999"d;
end;
if flag=1 then do;
if origination_date > intnx('month',month,-mob) then
origination_date=intnx('month',month,-mob);
end;
else do;
if flag = -1 and mob=0 then do;
if origination_date > month then
origination_date=month;
end;
end;
run;
proc sql;
create table want2 as
select account_id,month,mob,min(origination_date)as origination_date format=date9.
from want1
group by account_id
order by account_id,month;
quit;
输出:
+------------+-----------+-----+------------------+
| account_id | month | mob | origination_date |
+------------+-----------+-----+------------------+
| 11 | 01JAN2004 | 9 | 01APR2003 |
| 11 | 01FEB2004 | 10 | 01APR2003 |
| 11 | 01MAR2004 | 11 | 01APR2003 |
| 11 | 01JUN2008 | 0 | 01APR2003 |
| 12 | 01JAN2005 | -1 | 01MAR2005 |
| 12 | 01FEB2005 | -1 | 01MAR2005 |
| 12 | 01MAR2005 | 0 | 01MAR2005 |
| 12 | 01APR2005 | 1 | 01MAR2005 |
| 12 | 01MAY2005 | 2 | 01MAR2005 |
| 12 | 01JUN2005 | 3 | 01MAR2005 |
| 12 | 01DEC2006 | 0 | 01MAR2005 |
+------------+-----------+-----+------------------+