Условное соединение макросов Sas с использованием% if% then% else - PullRequest
1 голос
/ 27 сентября 2019

Я пытаюсь объединить две таблицы, вес 1 и вес2.Я хочу сначала объединить эти две таблицы с ID1 = ID2.если отсутствует идентификатор, я присоединюсь к DOB1 = DOB2.Я хочу, чтобы программа сравнивала каждую строку в таблице.но sas увидел, что первый идентификатор отсутствует в таблице weight2, затем он полностью переключился на оператор else и использовал DOB1 = DOB2 для присоединения.

Мой идеальный результат - объединить четыре строки.но теперь SAS дает мне только три ряда.

data weight1;    

   input ID1 $ Week1 DOB1; 

   datalines;            
1111 195  101
2222 220  102
3333 173  103
4444 135  104
;                           

proc print data=weight1;    
run; 

data weight2;    
  infile datalines missover;  
   input ID2 $ Week2 DOB2; 

   datalines;            
     195  101
2222 220  102
3333 173  103
4444 135  104
;                           

proc print data=weight2;    
run;  

options mlogic symbolgen mprint; 
%macro test ;
proc sql;
create table final as 
select a.ID1, a.DOB1, b.ID2,b.DOB2

from weight1 a
%if %sysfunc(exist(b.ID2)) %then 
inner join weight2 b 
on a.ID1 = b.ID2;
%else 
/*%if %sysfunc(not exist(b.IDnumber))*/
inner join weight2 b
on a.DOB1 = b.DOB2
;
;
quit;
%mend test;

%test

Sas log:

LOGIC(TEST):  Beginning execution.
MPRINT(TEST):   proc sql;
MLOGIC(TEST):  %IF condition %sysfunc(exist(b.ID2)) is FALSE
MPRINT(TEST):   create table final as select a.ID1, a.DOB1, b.ID2,b.DOB2 from weight1 a inner join weight2 b on a.DOB1 = b.DOB2 ;
NOTE: Table WORK.FINAL created, with 3 rows and 4 columns.

это мой идеальный результат

ID1    DOB1 ID2    DOB2
1111    101         101
2222    102 2222    102
3333    103 3333    103
4444    104 4444    104

Ответы [ 2 ]

0 голосов
/ 28 сентября 2019

A case выражение может использоваться в качестве критерия соединения.

Не использовать макрос.Вы используете %sysfunc(exist просто неправильно, функция exist проверяет наличие набора данных, а %sysfunc выполняется до времени компиляции исходного кода, а не во время выполнения SQL.

Использованиевыражение case для оценки предварительных условий проверки на равенство.

Пример:

data weight1;    

   input ID1 $ Week1 DOB1; 

   datalines;            
1111 195  101
2222 220  102
3333 173  103
4444 135  104
;                           

data weight2;    
  infile datalines missover;  
   input ID2 $ Week2 DOB2; 

   datalines;            
.    195  101
2222 220  102
3333 173  103
4444 135  104
;                           

proc sql;
  create table want as
  select a.ID1, a.DOB1, b.ID2,b.DOB2
  from weight1 a
  join weight2 b
    on case 
         when (a.id1 is not missing and b.id2 is not missing) then a.id1=b.id2
         when (a.dob1 is not missing and b.dob2 is not missing) then a.dob1=b.dob2
         else 0
       end
  ;

ПРИМЕЧАНИЕ. Случай реальных данных, когда в каждой таблице более одной строки с отсутствующим идентификатороми та же самая дата рождения вызовет мультипликативный эффект числа строк в таблице результатов.Например, этот пример данных:

1111 195  101
2222 220  102
3333 173  103
4444 135  104
.    145  105 ***
.    175  105 ***     

и

.    195  101
2222 220  102
3333 173  103
4444 135  104
.    155  105 ***
.    166  105 ***

4 = 2 x 2 строки результатов из помеченных данных.

0 голосов
/ 27 сентября 2019

Если вы доверяете соединению в DOB столько же, сколько и в ID, вы можете просто сделать on a.ID1 = b.ID2 or a.DOB1 = b.DOB2.Но я предполагаю, что DOB-совпадение может дать неправильные результаты, если идентификаторы не пропущены.

Вы можете сначала выбрать все строки, в которых у вас есть оба набора идентификаторов, а затем выбрать все строки, в которых совпадают DOB и какой-либо идентификатор отсутствует.Используйте union, чтобы получить их в одной таблице.Я не могу проверить свой код прямо сейчас, но что-то вроде этого:

proc sql;
create table final as 
select a.ID1, a.DOB1, b.ID2,b.DOB2
from weight1(where=(not missing(ID1)) a 
 inner join weight2(where=(not missing(ID2)) b 
 on a.ID1 = b.ID2
union
select a.ID1, a.DOB1, b.ID2,b.DOB2
from weight1 a 
 inner join weight2 b 
 on a.DOB1 = b.DOB2 and (missing(ID1) or missing(ID2))
;
...