Вы можете использовать экзистенциально-коррелированный подзапрос в выражении * 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;