Сравнение дат начала / окончания между различными строками на основе общего поля данных - PullRequest
1 голос
/ 24 июня 2019

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?     ║  
╚═════════╩═══════╩════════════╩══════════╩════════════╝  

Я хочу вернуть все, которые имеют одно и то же «событие», и где «конечная дата» для одного с более ранней «начальной_ датой» больше, чем (>) «начальная_дата» для другого с более поздней начальной__ датой.

Здесь субъект '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 Ответ

1 голос
/ 25 июня 2019

Способ обработки строк в группах на шаге DATA состоит в сортировке по ключу, а затем на шаге DATA используется BY key_field (event в вашем примере), retain извлечение данных из предыдущих строк в группа, идентифицируя первую и последнюю строку группы, используя if first.key_field и if 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 |

Посмотреть на БД Fiddle

...