Установить статус записи с группой по нескольким строкам в SAS - PullRequest
0 голосов
/ 26 января 2019

У меня есть таблица с двумя столбцами

create table incident 
(
  incident_name VARCHAR(256),
  APPStatus VARCHAR(20)
);

эта таблица имеет данные как

incident_name  |  APPStatus 
  first        |  In progress
  first        |  In progress
  first        |  done
  second       |  done
  second       |  overdue

Я хочу установить статус инцидента на основе столбца APPStatus, если, по крайней мере, один APPStatus находится в процессе обработки ,ident_status находится "в прогрессе"

или если просрочено инцидент_статус просрочен

Я пробовал

proc sql;
create table inc_status as
select incident_name, APPStatus,
incstatus = case when APSTATUS="In Progress" then "In Progress"
                 when APSTATUS="done" then "done"
                 else APSTATUS
            end
from incident 
group by incident_name ;
quit;

data  inc_status;
set incident ;
if APSTATUS="In Progress"
    then incstatus = "In Progress";
by incident_name ;
run;

но это не приводит к статусу инцидента как к группе по названию инцидента

Ожидаемый результат

incident_name  |  APPStatus      |  incstatus 
  first        |  In progress    |  In Progress
  first        |  In progress    |  In Progress
  first        |  done           |  In Progress
  second       |  done           |  overdue
  second       |  overdue        |  overdue

Ответы [ 2 ]

0 голосов
/ 26 января 2019

ваша логика была близка для sql.это либо для вашего статуса = в процессе, либо в срок

  proc sql;
    create table inc_status as
      select incident_name, appstatus,
               max(case when APPStatus="In progress" then "In progress"
             when APPStatus="overdue" then "overdue"
             else " "
        end) as inc
     from incident 
    group by incident_name;
   quit;

enter image description here

0 голосов
/ 26 января 2019

Вы можете использовать экзистенциально-коррелированный подзапрос в выражении * case, чтобы определить, какое значение присваивать сгруппированным элементам.

proc sql;
create table have
(
  incident_name VARCHAR(256),
  APPStatus VARCHAR(20)
);

insert into have
values ("first","In progress")
values ("first","In progress")
values ("first","done")
values ("second","done")
values ("second","overdue")
values ("third","done")
values ("third","welldone")
values ("fourth","In progress")
values ("fourth","overdue")
values ("fourth","done")
;


* case statement with existential correlated sub-queries;

create table want as
select 
  incident_name,
  appstatus,
  case 
    when exists (
      select * from have as inner 
      where inner.incident_name=outer.incident_name 
        and APPStatus="In progress"
    ) then "In Progress"
    when exists (
      select * from have as inner 
      where inner.incident_name=outer.incident_name 
        and APPStatus="overdue"
    ) then "overdue"
    else 
      " "
  end as incstatus
from have as outer
;

Другой подход заключается в использовании данных отображения (вместо жесткого кодирования экзистенциальных поисков в подзапросах). Левое объединение данных с агрегирующим подзапросом того же самого, который выбирает сопоставление для всей группы, которое нужно применить.

create table map
(
  APPStatus varchar(20),
  IncStatus varchar(20),
  priority int
);

insert into map
values ("In progress", "In Progress", 1)
values ("overdue", "overdue", 2)
;

create table want2 as
select 
  left.incident_name,
  left.APPStatus,
  right.IncStatus
from 
  have as left
left join 
  ( 
    select  distinct
      have.incident_name,
      map.IncStatus, 
      map.priority
    from
      have
    join 
      map
    on 
      have.APPStatus = map.APPStatus
    group by
      incident_name
    having
      priority=min(priority)
  ) as right
on
  left.incident_name = right.incident_name
;

Шаг DATA с обработкой DOW может вычислить значение для всей группы для применения к каждому элементу в группе. Способ вычисления зависит от ожидаемых условий значений состояния в каждой группе инцидентов. Если применяемое для всей группы значение имеет только одну отдельную возможность в группе, тогда логика проще. Более сложное вычисление будет учитывать несколько возможностей и выберет одно с наивысшим приоритетом:

data want3;
  do _n_ = 1 by 1 until (last.incident_name);
    set have;
    length IncStatus $20;
    by incident_name notsorted;

    * this select only works 100% if APPStatus that occur in a group are never multiple possible mappings;

    select (APPStatus);
      when ("In progress") IncStatus = "In Progress";
      when ("overdue") IncStatus = "overdue";
      otherwise IncStatus = IncStatus;
    end;
  end;

  do _n_ = 1 to _n_;
    set have;
    OUTPUT;
  end;
run;

data want4;
  * order of values listed is priority;
  array _source(2) $20 _temporary_ ("In progress", "overdue");
  array _target(2) $20 _temporary_ ("In Progress", "overdue");


  do _n_ = 1 by 1 until (last.incident_name);
    set have;
    length IncStatus $20;
    by incident_name notsorted;

    * _index is the priority aspect of the group-wide computation;
    * Negative is used because variable initializations done at
    * top of step by implicit loop will set _gwindex to missing.
    * Thus any first found _index (as negated) will be > _gwindex
    * (being missing per reset at top of step);
    * Also -1 > -2 so priority established by value order
    * in mapping arrays is maintained;

    _index = -whichc(AppStatus, of _source(*));
    if (_index) and (_index > _gwindex) then do; * gw ~ group-wide;
      _gwindex = _index;
      IncStatus = _target(-_index);
    end;
  end;

  do _n_ = 1 to _n_;
    set have;
    OUTPUT;
  end;

  drop _index _gwindex;
run;  
...