我有两张表格如下:
表1,用户列表:
Year Month Id Type
2010 3 1 A
2010 5 2 B
2010 10 1 A
2010 12 1 A
表2描述了用户推广历史记录:
Promote Date Id
2/20/2010 1
5/20/2010 1 (4/2010 the user got demoted, and after 1 month he got promote again)
从这两个表中,我需要生成一个喜欢表1的结果表,但是添加一个列,该类对A类用户进行分类,在过去3个月内或在特定日期超过3个月。例如,结果将是:
Year Month Id | Duration
2010 3 1 | A < 3 months
2010 10 1 | A > 3 months
2010 12 1 | A > 3 months
一般的想法是:
我目前有两个问题。
我不知道将月份列和年份列转换为月/日日期格式的最佳方法。
假设我已经从table1转换了月/年列,我使用Max函数从table2获取最近的日期。据我所知,max函数对性能不利,所以有没有其他解决方案而不是使用max?在mysql中,使用Limit 1很容易解决,但SAS proc-sql不支持Limit。在proc-sql中有没有相当于限制?以下是我目前正在考虑的代码。
PROC SQL;
Create table Result as SELECT table1.Year, table1.Month, table1.Code,
(Case When table1.Type = "B" then "B"
When table1.Type = "A" AND (table1.Date - (Select MAX(table2.Date) From table2 Where table2.Date <= table1.Date AND table2.Id = table1.Id ) < 90) THEN "A < 3 months"
When table1.Type = "A" AND (table1.Date - (Select MAX(table2.Date) From table2 Where table2.Date <= table1.Date AND table2.Id = table1.Id ) >= 90) THEN "A > 3 months"
When table1.Type = "C" then "C"
end) as NewType
From table1
LEFT JOIN
// ....
;
QUIT;
正如你所看到的,我需要将table1与其他表连接起来,所以我使用了子查询,这也是一个糟糕的表现,但我不知道是否还有其他方法。感谢帮助和建议。
答案 0 :(得分:4)
您可以使用mdy()
函数创建日期值,如下所示:
data have;
input Year Month Id Type $;
datalines;
2010 3 1 A
2010 5 2 B
2010 10 1 A
2010 12 1 A
;
run;
data have;
set have;
format date date9.;
date = mdy(Month, 1, Year);
run;
您没有日期值,所以我只使用了1(每个创建的日期都是本月的第一天)。
现在,您可以按ID加入这两个表,并计算第一个表中的日期与第二个表中的促销日期之间的差异:
proc sql;
create table want as
select *
,abs(date - promote) as diff
from have as a
left join
prom as b
on a.id = b.id;
quit;
之后,按id,date和diff对结果表进行排序:
proc sort data=want;
by id date diff;
run;
排序数据集后如下所示:
Year Month Id Type date Promote diff
---------------------------------------------------
2010 3 1 A 01MAR2010 20FEB2010 9
2010 3 1 A 01MAR2010 20MAY2010 80
2010 5 2 B 01MAY2010 . .
2010 10 1 A 01OCT2010 20MAY2010 134
2010 10 1 A 01OCT2010 20FEB2010 223
2010 12 1 A 01DEC2010 20MAY2010 195
2010 12 1 A 01DEC2010 20FEB2010 284
最后一步,遍历数据集并检查每个ID和日期值的第一个diff
值是否更低,或者是否超过3个月(我只检查了90天,您也可以使用{{1功能)。因为我们按id,date和diff对数据集进行排序,所以第一行应该最接近日期,所以你intck
只有第一行。
output
使用 data want2(keep = year month id type duration);
set want;
by date;
if first.date and Type = 'A' then do;
if diff lt 90 then do;
duration = 'A < 3 months';
output want2;
end;
if diff gt 90 then do;
duration = 'A > 3 months';
output want2;
end;
end;
else if first.date then do;
duration = type;
output want2;
end;
run;
语句是因为我们只想保留一些行(每个行的第一行)。最后output
就是那样,类型值不同于A的行也会保留在最终结果中。
这是最终结果:
output