我有一个两列的表
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
答案 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)