根据通用数据字段比较不同行之间的开始/结束日期

时间:2019-06-24 18:31:45

标签: sas

SAS 9.4

示例数据集

╔═════════╦═══════╦════════════╦══════════╗  
║ subject ║ event ║ start_date ║ end_date ║  
╠═════════╬═══════╬════════════╬══════════╣  
║ s1      ║ e1    ║ 2-Mar-19   ║ 1-Jun-19 ║  
║ s2      ║ e1    ║ 1-Mar-19   ║ 1-May-19 ║  
╚═════════╩═══════╩════════════╩══════════╝ 

预期输出:

╔═════════╦═══════╦════════════╦══════════╦════════════╗  
║ subject ║ event ║ start_date ║ end_date ║ query_text ║  
╠═════════╬═══════╬════════════╬══════════╬════════════╣   
║ s1      ║ e1    ║ 1-Mar-19   ║ 1-Jun-19 ║ error?     ║  
║ s2      ║ e1    ║ 1-Mar-19   ║ 1-May-19 ║ error?     ║  
╚═════════╩═══════╩════════════╩══════════╩════════════╝  

我想返回所有具有相同“事件”,并且其中一个具有较早“ start_date”的“ end_date”大于(>)另一个具有较晚“ start_date”的“ start_date”的所有事件。

在这里,主题“ s2”的“ start_date”早于“ s1”,但“ s2”的“ end_date”晚于“ s1”的“ start_date”,所以这两个将被返回

到目前为止,这是我所拥有的,但是我不确定如何确保我要比较的内容具有相同的“事件”:

data Out_2;   
/* set relevant dataset */   
if input(compress(end_date,"/"), ??date9.) > input(compress(start_date,"/"), ??date9.);  

/* do something */  

run;

谢谢

1 个答案:

答案 0 :(得分:1)

在DATA步骤中处理组中行的方式是按键排序,然后在DATA步骤中使用BY key_field(在您的示例中为event),retain数据来自组中前几行,同时使用if first.key_fieldif last.key_field来标识该组的第一行和最后一行。

如果每个事件最多包含两个主题,那将很容易。如果您有更多内容,则必须编写重复的代码来保留第一行,第二行等中的值,或将数据保留到数组中。

因此,我放弃了DATA步骤,转而使用SQL,这使您可以轻松地做到这一点:

proc sql;
    create table result as
    select i1.*
      from example_input i1,
           example_input i2
     where i1.event = i2.event
       and i1.subject ^= i2.subject
       and (
             (i1.start_date < i2.start_date and
              i1.end_date > i2.start_date
             ) 
           or /* the other way around */
             (i2.start_date < i1.start_date and
              i2.end_date > i1.start_date
             )
           )
   ; /* untested - I don't have SAS handy */
quit;

此SQL在您的输入数据上获得的输出(不是在SAS中,但是我很确定它不会给出不同的结果!):

| subject | event | start_date | end_date   |
| ------- | ----- | ---------- | ---------- |
| s1      | e1    | 2019-03-02 | 2019-06-01 |
| s2      | e1    | 2019-03-01 | 2019-05-01 |

View on DB Fiddle