BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Ronein
Onyx | Level 15

Hello,

With continue to my previous question:

I need to perform merge that can by one variable or two variables (depends on number of vars in the macro).

 

My question:

How to change the following code lines to dynamic code that is taking the variables in List1 macro

on a.Cylinders=b.Cylinders
and a.Horsepower=b.Horsepower

 

 

%macro BBB(mon,sourceTbl,TargetTbl,list1=,list2=);
%let nr_vars=%sysfunc(countw(&list1.));
%put &nr_vars.;
proc sql;
create table New_tbl as
select
%do j = 1 %to &nr_vars.;
  put(%scan(&list1.,&j.),%scan(&list2.,&j.).) as %scan(&list1.,&j.),
%end;
  count(*) as nr&mon. format=comma21.,
  calculated nr&mon./(select count(*) as total from  &sourceTbl.) as PCT&mon. format=percent8.1
from &sourceTbl.
%if &nr_vars. > 0
%then %do;
group by 
  %do j = 1 %to &nr_vars.;
  %if &j. > 1 %then ,;
  calculated %scan(&list1.,&j.)
  %end;
%end;
;
quit;


%MACRO RRR1;
%if %sysfunc(exist(&TargetTbl.)) %then %do;
proc sql ;
create table New as
select  a.*,b.nr&mon.,b.PCT&mon.
from &TargetTbl. as a
left join New_tbl as b
on a.Cylinders=b.Cylinders
and a.Horsepower=b.Horsepower
/***Here I want to have a dynamic problem that is taking the variables in List1***/
;
quit;
%end; 

%else %do;
Data &TargetTbl.;
set New_tbl;
Run;
%end; 
%MEND RRR1;
%RRR1;
%mend BBB;
  
/*Distribution by grouped Cylinders+grouped Horsepower***/
/*Distribution by grouped Cylinders+grouped Horsepower***/
/*Distribution by grouped Cylinders+grouped Horsepower***/
proc format;
value F1mt
.='Uknown'
1-4='1-4'
5-high='5+'
;
Run;
proc format;
value F2mt
.='Uknown'
low-80='0-80'
80-120='80-120'
120-180='120-180'
180-high='180+'
;
Run;
%BBB(mon=2204,
sourceTbl=sashelp.cars,
TargetTbl=wanted,
list1=Cylinders Horsepower,
list2=F1mt  F2mt)
  

Data cars2205;/***YYMM**/
input Cylinders Horsepower;
cards;
4 110
4 90
5 120
6 185
4 130
7 250
4 130
5 190
4 76
4 91
8 410
;
run;


%BBB(mon=2205,
sourceTbl=cars2205,
TargetTbl=wanted,
list1=Cylinders Horsepower,
list2=F1mt  F2mt)
 
 
1 ACCEPTED SOLUTION

Accepted Solutions
yabwon
Amethyst | Level 16

Try this:

%macro myJoin(list1, list2);

%local a b c d;

%let a = %scan(&list1.,  1);
%let b = %scan(&list1., -1);

%let c = %scan(&list2.,  1);
%let d = %scan(&list2., -1);

proc sql;
select t1.age, t2.name
from 
sashelp.class as t1
join
sashelp.class as t2
on
t1.&a. = t2.&c.
and
t1.&b. = t2.&d.
;
run;

%mend;


options mprint;
%myJoin(name, name)

%myJoin(name age, name age)

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



View solution in original post

3 REPLIES 3
yabwon
Amethyst | Level 16

Try this:

%macro myJoin(list1, list2);

%local a b c d;

%let a = %scan(&list1.,  1);
%let b = %scan(&list1., -1);

%let c = %scan(&list2.,  1);
%let d = %scan(&list2., -1);

proc sql;
select t1.age, t2.name
from 
sashelp.class as t1
join
sashelp.class as t2
on
t1.&a. = t2.&c.
and
t1.&b. = t2.&d.
;
run;

%mend;


options mprint;
%myJoin(name, name)

%myJoin(name age, name age)

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



Ronein
Onyx | Level 15
May you please explain your code ?
Why did you write minus 1 and plus 1 in scan function?
Will this technique work well when there will be only one variable to match in merge ?
Ronein
Onyx | Level 15

Great, very clever solution.

As I understand "1"  takes the first element and "-1" takes the last.

If there is one element than first and last are same.

If there are 2 elements then "1" takes the first and  "-1" takes the last.

The only thing need to modify is that need only 2 macro vars a,b because list1 is the explanatory variables and list2 is the correspondence  formats.

Here is the solution that was made thanks to your advice

%macro BBB(mon,sourceTbl,TargetTbl,list1=,list2=);

%local a b nr_vars;
%let a = %scan(&list1.,  1);
%let b = %scan(&list1., -1);
 
%let nr_vars=%sysfunc(countw(&list1.));
%put &nr_vars.;
proc sql;
create table New_tbl as
select
%do j = 1 %to &nr_vars.;
  put(%scan(&list1.,&j.),%scan(&list2.,&j.).) as %scan(&list1.,&j.),
%end;
  count(*) as nr&mon. format=comma21.,
  calculated nr&mon./(select count(*) as total from  &sourceTbl.) as PCT&mon. format=percent8.1
from &sourceTbl.
%if &nr_vars. > 0
%then %do;
group by 
  %do j = 1 %to &nr_vars.;
  %if &j. > 1 %then ,;
  calculated %scan(&list1.,&j.)
  %end;
%end;
;
quit;


%MACRO RRR1;
%if %sysfunc(exist(&TargetTbl.)) %then %do;
proc sql ;
create table New as
select  t1.*,
coalesce(t2.nr&mon.,0 )  as nr&mon. format=comma21.,
coalesce(t2.PCT&mon.,0 ) as PCT&mon. format=percent8.1
from &TargetTbl. as t1
left join New_tbl as t2
on 
t1.&a. = t2.&a.
and
t1.&b. = t2.&b.
/***Here I want to have a dynamic problem that is taking the variables in List1***/
;
quit;
%end; 

%else %do;
Data &TargetTbl.;
set New_tbl;
Run;
%end; 
%MEND RRR1;
%RRR1;
%mend BBB;
  
/*Distribution by grouped Cylinders+grouped Horsepower***/
/*Distribution by grouped Cylinders+grouped Horsepower***/
/*Distribution by grouped Cylinders+grouped Horsepower***/
proc format;
value F1mt
.='Uknown'
1-4='1-4'
5-high='5+'
;
Run;
proc format;
value F2mt
.='Uknown'
low-80='0-80'
80-120='80-120'
120-180='120-180'
180-high='180+'
;
Run;
%BBB(mon=2204,
sourceTbl=sashelp.cars,
TargetTbl=wanted,
list1=Cylinders Horsepower,
list2=F1mt  F2mt)
  

Data cars2205;/***YYMM**/
input Cylinders Horsepower;
cards;
4 110
4 90
5 120
6 185
4 130
7 250
4 130
5 190
4 76
4 91
8 410
;
run;


%BBB(mon=2205,
sourceTbl=cars2205,
TargetTbl=wanted,
list1=Cylinders Horsepower,
list2=F1mt  F2mt)
 
How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 3 replies
  • 956 views
  • 1 like
  • 2 in conversation