SAS Proc SQL获取具有特定日期的最近日期的记录

时间:2013-03-02 07:32:15

标签: sql date sas proc-sql

我有两张表格如下:

表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    

一般的想法是:

  • 我需要将月份列和年份列从表1转换为a 日期格式如3/2010
  • 将最近的促销日期减去新转换后的值 上述日期(2010年2月)以获取用户的天数 促进
  • 比较90天将其提升的持续时间分类

我目前有两个问题。

我不知道将月份列和年份列转换为月/日日期格式的最佳方法。

假设我已经从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与其他表连接起来,所以我使用了子查询,这也是一个糟糕的表现,但我不知道是否还有其他方法。感谢帮助和建议。

1 个答案:

答案 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