BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
mcook
Quartz | Level 8

there have been many occasions where i've wanted to be able to do this, but have not been able to figure it out.

 

Given the following table and code to select the values of column C into a macrovariable "foods" separated by a space ( or really any delimiter).

 

data TestTable;
	input A $ B C $;
	datalines;
Mitch 10 milk
Ed 14 tuna
Phil 45 bread
Bonnie 17 butter
;
run;

proc sql noprint;
	select C into :foods
		separated by ' '
	from TestTable;
quit;

%PUT foods=&foods.;

Is there a way to use that macrovariable in an in operator, such as the following?

 

 

proc sql noprint;
	create table RandomTable1 as
		select * from RandomTable2
			where RandomColumn in ("milk" "tuna" "bread" "butter");
quit;

With the values of the macrovariable as the values of the in operator?

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Ksharp
Super User


%let food= SUV Sedan Sports ;

proc sql;
create table want as
 select * from sashelp.cars
  where findw(symget('food'),strip(type));
quit;

View solution in original post

18 REPLIES 18
mcook
Quartz | Level 8
Please ignore my misspelling of Where in the title 🙂
PeterClemmensen
Tourmaline | Level 20

I don't recommend it, but yes, you can do something like this

 

See if you can use this as a template

 

data TestTable;
	input A $ B C $;
	datalines;
Mitch 10 milk
Ed 14 tuna
Phil 45 bread
Bonnie 17 butter
;
run;

proc sql noprint;
	select quote(compress(C)) into :foods
		separated by ', '
	from TestTable
   where C in ("milk", "tuna");
quit;

%PUT foods=&foods.;

proc sql noprint;
	create table want as
		select * from TestTable
			where C in (&foods.);
quit;
Tom
Super User Tom
Super User

Don't use COMPRESS() on the strings.  If they have any leading or embedded spaces then the resulting quoted strings will not match the values in the data.

Tom
Super User Tom
Super User

If you intend to use the macro variable in that way then include quotes in the value so you can simply use the macro variable to replace the hardcoded list of string literals.

 

select distinct quote(trim(C)) into :foods separated by ' ' from TestTable;
...
where RandomColumn in (&foods)
...
Tom
Super User Tom
Super User

Note that the IN operator does not need commas.

Kurt_Bremser
Super User

@Tom wrote:

Note that the IN operator does not need commas.


But it accepts them, while the WHEN statement requires them. So I always use commas, as I've found that I often convert IF/THEN/ELSE statements with an IN operator to SELECT blocks.

Tom
Super User Tom
Super User

@Kurt_Bremser wrote:

@Tom wrote:

Note that the IN operator does not need commas.


But it accepts them, while the WHEN statement requires them. So I always use commas, as I've found that I often convert IF/THEN/ELSE statements with an IN operator to SELECT blocks.


Sure but the commas make it difficult to pass the strings as arguments to macro functions or macro calls.

Quentin
Super User

You have a delimited list of items in a macro variable.  To use it with in IN operator, you need to add quote marks around each item (and may want to add a comma delimiter, for fun).

 

I'm a big fan of @RichardDeVen 's utitly macro %seplist: https://www.devenezia.com/downloads/sas/macros/index.php?m=seplist

 

Given a delimited list of items, it will add quotes (or whatever you want) around each item, change the delimiter, etc.

 

1
2    %let foods=milk tuna bread butter ;
3
4    %put %seplist(&foods,nest=QQ,dlm=%str(,)) ;
"milk","tuna","bread","butter"

You can use like:

 

proc sql noprint;
	create table RandomTable1 as
		select * from RandomTable2
			where RandomColumn in (%seplist(&foods,nest=QQ,dlm=%str(,)));
quit;

 

Generally I like to keep my macro variable lists without quote marks, and either space-delimited or pipe-delimited.  %SepList makes it easy to change delimiters or add quote marks when needed.

 

BASUG is hosting free webinars ! Check out recordings of our past webinars: https://www.basug.org/videos. Save the date for our in person SAS Blowout on Oct 18 in Cambridge, MA. Registration opens in September.
mcook
Quartz | Level 8

Soon after posting I had an idea. And wrote a quick macro to add quotes around each of the values in the macrovariable.  

 

So far it seems to work correctly. With the constraint that the values be space delimited, with no internal spaces.

 

*InVars must be space separated with no internal spaces in the values;
*VarName is Name of Global Variable ouputted, with quotes around each value.;
%MACRO K(VarName,InVars);
	%LET MVar1=;

	%DO J=1 %TO %SYSFUNC(CountW(&InVars.));
		%LET JJ=%SCAN(&InVars.,&J.);
		%LET quote&J.="&JJ.";
		%LET MVar1=&MVar1. &&quote&J.;
	%END;

	%GLOBAL &VarName.;
	%LET &VarName.=&MVar1.;
	%PUT &Varname.=&MVar1.;
%MEND K;
Tom
Super User Tom
Super User

Looks good.  Make sure to define your local macros using %LOCAL statement so that programs that call that macro don't get supprised when the value their macro variables named MVAR1 and JJ and the others you are creating get changed.

 

Also look into making it a "function" macro.  Like the one mentioned above. Or this one:  https://github.com/sasutils/macros/blob/master/qlist.sas

mcook
Quartz | Level 8

Arent macrovariables created within a macro local to that macro by default?  With any other macrovariables outside that macro unaffected, regardless of having the same name?  

Tom
Super User Tom
Super User

Macro variables created within a macro are only local to that macro if the macro variable does not already exist.

If the macro variable with that name already exists (either GLOBAL or in the local scope of another macro that has called this one) then that macro variable is used.

The purpose of the %LOCAL statement is to insure that your macro is not changing macro variables previously defined.  So to avoid unwanted side effects of running the macro.

ballardw
Super User

Try this code:

%macro prob(x=);
%do i = 1 %to &x;
  %put Writing i in Prob: &i;
%end;
%mend;
%macro driver(n=);
%do i= 1 %to &n;
   %prob(x=3)

   %put Writing i in Driver: &i.;
%end;
%mend;

%driver(n=2)

Then add a %local i to the Prob macro and recompile the macro and run the code.

See the difference?

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 18 replies
  • 1584 views
  • 5 likes
  • 7 in conversation