设置SAS中按多行分组的记录的状态

时间:2019-01-26 10:44:24

标签: sas

我有一个两列的表

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正在进行,则event_status为“处于怀孕状态”

或者如果已过期,则event_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;

,但不是按event_name分组的事件状态

预期结果

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 :(得分:0)

您可以在case的when表达式中使用与存在相关的子查询,以确定要分配给分组项目的值。

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
;

具有DOW处理的DATA步骤可以计算整个组范围的值以应用于组中的每个项目。如何进行计算取决于每个事件组中状态值的预期条件。如果要应用的整个组范围的值在组中只有一种不同的可能性,则逻辑会更简单。一种更复杂的计算会考虑多种可能性,并选择优先级最高的一种:

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;  

答案 1 :(得分:0)

您的逻辑对于sql是关闭的。这适用于您的状态为=进行中或到期的情况

href="#pos1"

enter image description here