Существует много способов поиска в SAS.
Прежде всего, я бы предложил исключить дублирование вашей таблицы поиска (например, с помощью PROC SORT и Data Step / Set)./ By) - решение о том, какой дубликат оставить (если он существует).
Что касается самой задачи поиска, для простоты и изучения я бы предложил следующее:
Способ "СТАРАЯ ШКОЛА"- хорошо подходит для аудита входных и выходных данных (легче проверить результаты объединения, когда входные таблицы расположены в требуемом порядке):
*** data to validate;
data have;
length name $10. age 4. friend $10.;
input name age friend;
datalines;
Jon 11 Ann
Jon 11 Tom
Jimb 12 Egg
Joe 11 Egg
Joe 11 Anne
Joe 11 Tom
Jed 10 Ann
run;
*** lookup table;
data corrections;
length current_names $10. resolved_names $10.;
input current_names resolved_names;
datalines;
Jon John
Ann Anne
Jimb Jim
run;
*** de-duplicate lookup table;
proc sort data=corrections nodupkey; by current_names; run;
proc sort data=have; by name; run;
data have_corrected;
merge have(in=a)
corrections(in=b rename=(current_names=name))
;
by name;
if a;
if b then do;
name=resolved_names;
end;
run;
Способ SQL - который позволяет избежать сортировки таблицы имён:
proc sql;
create table have_corrected_sql as
select
coalesce(b.resolved_names, a.name) as name,
a.age,
a.friend
from work.have as a left join work.corrections as b
on a.name eq b.current_names
order by name;
quit;
Обратите внимание: Coalesce () используется для замены отсутствующих значений resolved_names (т. Е. Когда нет коррекции) именами из таблицы имён
EDIT: чтобы отразить комментарий Квентина (ПРАВИЛЬНЫЙ), который яя пропустил обновление как имен, так и полей друзей.
Основываясь на исправлении 2 полей, снова много подходов, но суть в том, чтобы обновлять значение только в том случае, если оно существует в поиске (исправлениях).возможность.Хеш-объект довольно хорош в этом, как только вы поняли, что это объявление.
Примечание: любые ключевые поля в объекте Hash необходимо указывать в операторе Length BEFOREHAND.
EDIT: согласно альтернативе ChrisJ объявлению оператора Length и моему ответу (см. Ниже)- было бы лучше указать, что ключевые переменные должны быть определены ДО того, как вы объявите хеш-таблицу.
data have_corrected;
keep name age friend;
length current_names $10.;
*** load valid names into hash lookup table;
if _n_=1 then do;
declare hash h(dataset: 'work.corrections');
rc = h.defineKey('current_names');
rc = h.defineData('resolved_names');
rc = h.defineDone();
end;
do until(eof);
set have(in=a) end=eof;
*** validate both name fields;
if h.find(key:name) eq 0 then
name = resolved_names;
if h.find(key:friend) eq 0 then
friend = resolved_names;
output;
end;
run;
РЕДАКТИРОВАТЬ: ответить на комментарии относительно альтернативы ChrisJ SQL / Update
В основном,вам нужно ограничить каждую инструкцию UPDATE ТОЛЬКО теми строками, которые имеют значения имен или значения друзей в таблице исправлений - это делается добавлением еще одной инструкции where ПОСЛЕ того, как вы указали set var = (предложение).См. Ниже.
Примечание.AFAIK, решение SQL вашего требования потребует БОЛЕЕ 1 прохода как базовой таблицы, так и таблицы поиска.
Однако для просмотра / хэш-таблицы требуется один проход базовой таблицы, загрузка таблицы поиска и затем сами действия поиска.Вы можете увидеть разницу в производительности в журнале ...
proc sql;
*** create copy of have table;
create table work.have_sql as select * from work.have;
*** correct name field;
update work.have_sql as u
set name = (select resolved_names
from work.corrections as n
where u.name=n.current_names)
where u.name in (select current_names from work.corrections)
;
*** correct friend field;
update work.have_sql as u
set friend = (select resolved_names
from work.corrections as n
where u.friend=n.current_names)
where u.friend in (select current_names from work.corrections)
;
quit;