SAS SQL: объединить последовательные строки с пустой датой, если следующая строка отличается - PullRequest
0 голосов
/ 11 марта 2019

У меня есть таблица t1 с полями activity_name (целое число) и status_change_dttm (дата):

activity_name status_change_dttm
------1------  -------null-------  
------1------  -------null-------  
------1------  18FEB2019:19:16:13  
------2------  -------null-------  
------3------  -------null-------  
------3------  -------null-------  
------3------  -------null-------  
------4------  -------null-------  
------5------  03FEB2019:14:38:52  
------5------  04FEB2019:18:30:52
------5------  14FEB2019:12:00:12

Результат должен выглядеть следующим образом:

activity_name status_change_dttm   
------1------  18FEB2019:19:16:13  
------2------  -------null-------  
------3------  -------null-------   
------4------  -------null-------  
------5------  03FEB2019:14:38:52  
------5------  04FEB2019:18:30:52  
------5------  14FEB2019:12:00:12

Так что, если у меня есть строки с одинаковыми activity_name и нулевыми значениями в status_change_dttm, а следующее действие не равно предыдущему, мне нужно объединить эти строки в одну строку. Если у меня есть строки с нулевыми значениями в status_change_dttm, а следующая строка с такими же activity_name и status_change_dttm не равна нулю, мне нужно удалить только строки с нулевыми значениями.
Заключить:

1) IF NULL - NULL - DATE - next activity -> drop nulls  
2) IF NULL - NULL - NULL - next activity -> merge into one row  
3) IF DATE - DATE - DATE - next activity -> no changes  
4) IF one NULL - next activity -> no changes  
5) IF one DATE - next activity -> no changes 

Я полагаю, что ключ - это функции задержки / опережения, но я не понимаю общей концепции. Спасибо.

Ответы [ 2 ]

0 голосов
/ 14 марта 2019

Решение шага данных SAS может быть следующим:

/* set up data */
data have;
   infile datalines truncover;

   input activity_name      :         8.
         status_change_dttm : datetime20.
   ;

   format status_change_dttm datetime20.;

   datalines;
1 
1 
1 18FEB2019:19:16:13
2 
3 
3 
3 
4 
5 03FEB2019:14:38:52
5 04FEB2019:18:30:52
5 14FEB2019:12:00:12
15 
15 04FEB2019:18:30:52
15 14FEB2019:12:00:12
;


/* process and output */
data want;
   null_count  = 0;
   group_count = 0;

   /* count number of records and nulls for this activity_name group */
   do until(last.activity_name);
      set have;
      by activity_name;

      group_count + 1;

      if missing(status_change_dttm) then
         null_count + 1;
   end;

   /* output data for the same activity_name group */
   do until(last.activity_name);
      set have;
      by activity_name;

      if null_count = 0 then
         output;
      else
         if null_count eq group_count then
         do;
            output;
            /* prevent any more null records being output */
            null_count + 1;
         end;
         else
            if null_count lt group_count and not missing(status_change_dttm) then
               output;
   end;
run;
0 голосов
/ 11 марта 2019

Хммм.,,Это почти делает то, что вы хотите:

select distinct t.activity_name, t.status_change_dttm
from t1 t;

Однако, это вернет NULL значения, даже если существуют не-NULL значения, например, для 1. Чтобы предотвратить это:

select distinct t.activity_name, t.status_change_dttm
from t1 t
where t.activity_name is not null or
      not exists (select 1
                  from t1 t2
                  where t2.activity_name = t.activity_name and
                        t2.status_change_dttm is not null
                 );

Примечание: select distinct в этом случае может не понадобиться.

...