Solved
N/A
Posts: 0

What is the format for multiple conditions in IF logic?

I've searched the 'net and looked in the book, "The Little SAS book", and am still slightly confused. What is the way to write a multiple condition If statement? For example,

If conditiona or conditionb or conditionc or conditiond then do;
more lines of code
some more code
end;
else if conditiona and conditionb and conditionc end conditiond then do;
code goes here
some more code
end;

The reason I ask is because my code hits the first multiple condition and executes whether any of the conditions are true or not and then goes and executes the rest of the code.

If someone has a suggestion, I'd like to hear it. Thanks!

Accepted Solutions
Solution
‎03-03-2017 02:46 PM
SAS Super FREQ
Posts: 8,869

Re: What is the format for multiple conditions in IF logic?

[ Edited ]

Editor's note: Thanks to Cynthia for this answer.  Also, for the macro solution to how %IF conditions work see Cynthia's answer later down in this post.

Hi...
You CANNOT code
[pre]
if region = 'Asia' or 'Canada' or 'Pacific' then do;
[/pre]
you have to do something like this:
[pre]
IF region = 'Asia' or region = 'Canada' or region = 'Pacific' then do;
...statements ...;
end;
else if region = 'Western Europe' or region = 'United States' then do;
...statements ...;
end;
[/pre]

OR you CAN have
[pre]
if region in ('Asia', 'Canada', 'Pacific') then do;
...statements...
end;
else if region in ('Western Europe', 'United States') then do;
...statements...
end;
[/pre]

cynthia

All Replies
Solution
‎03-03-2017 02:46 PM
SAS Super FREQ
Posts: 8,869

Re: What is the format for multiple conditions in IF logic?

[ Edited ]

Editor's note: Thanks to Cynthia for this answer.  Also, for the macro solution to how %IF conditions work see Cynthia's answer later down in this post.

Hi...
You CANNOT code
[pre]
if region = 'Asia' or 'Canada' or 'Pacific' then do;
[/pre]
you have to do something like this:
[pre]
IF region = 'Asia' or region = 'Canada' or region = 'Pacific' then do;
...statements ...;
end;
else if region = 'Western Europe' or region = 'United States' then do;
...statements ...;
end;
[/pre]

OR you CAN have
[pre]
if region in ('Asia', 'Canada', 'Pacific') then do;
...statements...
end;
else if region in ('Western Europe', 'United States') then do;
...statements...
end;
[/pre]

cynthia

N/A
Posts: 0

Re: What is the format for multiple conditions in IF logic?

Thanks, Cynthia.....

How would that look in a macro...something like this:

%if region = 'Asia' or region = 'India' %then %do;
.....statements....
%end;
%else %if region = 'Canada' or region = 'Europe' %then %do;
...statements....
%end;

The reason I ask is because, yes, I'm coding in a macro within a stored process and the thing isn't working the way I expect it to . I will try to port it to native SAS code and hard code some variables to see what happens, but that just seems to be a lot of extra work, to do it in native code, then change out the hard-coded variables and then put it into a stored process.

Anyway...any ideas on why something like a multiple condition IF doesn't work properly in a macro?

Thanks!
SAS Super FREQ
Posts: 8,869

Re: What is the format for multiple conditions in IF logic?

It looks like you are trying to test data step variables in a %IF statement. That technique won't work the way you have envisioned. In the HELP topic, Macro Language Dictionary --> %IF-%THEN/%ELSE Statement, it outlines the difference between how %IF differs from DATA step IF. The whole explanation is worthwhile reading. The bottom line is (from the doc):
"The expression that is the condition for the %IF-%THEN/%ELSE statement can contain only operands that are constant text or text expressions that generate text. However, the expression that is the condition for the IF-THEN/ELSE statement can contain only operands that are DATA step variables, character constants, numeric constants, or date and time constants.

When the %IF-%THEN/%ELSE statement generates text that is part of a DATA step, it is compiled by the DATA step compiler and executed. On the other hand, when the IF-THEN/ELSE statement executes in a DATA step, any text generated by the macro facility has been resolved, tokenized, and compiled. No macro language elements exist in the compiled code. "

The key statements are "The expression that is the condition for the %IF-%THEN/%ELSE statement can contain only operands that are constant text or text expressions that generate text" and "No macro language elements exist in the compiled code." I cannot stress enough my recommendation that you follow these 4 steps:
1) have a working SAS program that executes correctly in an EG code node or from Display Manager with hardcoded values for all selection criteria;
2) take the program from #1 and "macro-ize" it with macro variables. Test the program in an EG code node or from SAS Display Manager by populating the macro variable values with %LET statements;
3) Turn the program from #2 into a MACRO program and add the MACRO conditional logic that you need to implement to make the macro generate all the outputs that you want.
4) When the MACRO program from #3 is working correctly, THEN and ONLY THEN, turn the #3 program into a stored process.

For example, in this program below, the macro variable &WANTREG is the equivalent of what might come from the client application. I want, in my data step to selectively set the value of the BONUS_FACTOR variable depending on what they chose as their macro parameter value. This is the equivalent of a step 3 program that has not yet been turned into a stored process. I show 3 different and ways to work with both DATA Step logic and Macro conditional logic. At the point when I am ready to turn this program into a stored process, I would probably pick one method or the other instead of having all 3 methods.

Again, this program is NOT intended to be executed as a stored process. It is intended to be execute in a code node--so you can examine the output and the SAS Log. Carefully look at the code that has actually been sent to the compiler for each of the 4 values for &WANTREG -- you can find this in the SAS Log by looking for the lines preceded by MPRINT. If you need help figuring out how to make your macro program work, your best bet, at this point, is to contact Tech Support.

cynthia
[pre]
** the code;

options mprint mlogic symbolgen;

%macro test;
%global wantreg;

** not using macro logic at all;
** but using macro variable to make a data step variable;
** for comparison purpose with a DATA STEP IF;
data select1;
set sashelp.shoes;
length theywant \$25;
theywant = "&wantreg";
if region = theywant then do;
if theywant = "Asia" then do;
bonus_factor = .10;
end;
else if theywant ne "Asia" then do;
bonus_factor = .05;
end;
bonus = sales * bonus_factor;
output;
end;
run;

** Using macro variable in comparison to a data set variable;
** in a where clause and in a DATA step IF;
data select2;
set sashelp.shoes;
where region = "&wantreg";

if "&wantreg" = "Asia" then do;
bonus_factor = .10;
end;
else if "&wantreg" ne "Asia" then do;
bonus_factor = .05;
end;

bonus = sales * bonus_factor;
output;
run;

** using macro logic in a data step program to write conditional code;
** and also do selection. NOTE that in macro '%IF', there are NO;
** quotes around values for comparison to macro variables;
data select3;
set sashelp.shoes;
if region = "&wantreg" then do;
%if &wantreg = Asia %then %do;
bonus_factor = .10;
flag = 'using %if &wantreg = Asia';
%end;
%else %if &wantreg ne Asia %then %do;
bonus_factor = .05;
flag = 'using %if &wantreg ne Asia';
%end;
bonus = sales * bonus_factor;
output;
end;
run;

** create macro variable for each of above data set creation methods;
proc sql noprint;
select nobs into :numobs1 from dictionary.tables
where libname = 'WORK' and memname = 'SELECT1';
quit;

proc sql noprint;
select nobs into :numobs2 from dictionary.tables
where libname = 'WORK' and memname = 'SELECT2';
quit;

proc sql noprint;
select nobs into :numobs3 from dictionary.tables
where libname = 'WORK' and memname = 'SELECT3';
quit;

** macro condition to execute whole sections of code;
%if &numobs1 = 0 or &numobs2 = 0 or &numobs3 = 0 %then %do;
%put !-------------------------------------!;
%put Guess what? You entered: &wantreg ;
%put and the correct way to enter that value is %sysfunc(propcase(&wantreg));
%put !-------------------------------------!;

data errmsg;
dsn = "WORK.SELECT1";
obs_created = &numobs1;
output;
dsn = "WORK.SELECT2";
obs_created = &numobs2;
output;
dsn = "WORK.SELECT3";
obs_created = &numobs3;
output;
run;

proc print data=errmsg;
title 'There were no observations selected for this value';
title2 "WANTREG macro variable = &WANTREG";
run;
%end;
%else %do;
%if &numobs1 gt 0 %then %do;
proc print data=select1(obs=10);
var region product sales bonus_factor bonus;
title 'Query Successful. DSN = WORK.SELECT1';
run;
%end;
%if &numobs2 gt 0 %then %do;
proc print data=select2(obs=10);
var region product sales bonus_factor bonus;
title 'Query Successful. DSN = WORK.SELECT2';
run;
%end;
%if &numobs3 gt 0 %then %do;
proc print data=select3(obs=10);
var region product sales bonus_factor bonus flag;
title 'Query Successful. DSN = WORK.SELECT3';
run;
%end;
%end;

%mend test;

%test;

%let wantreg = Asia;
%test;

%let wantreg = ASIA;
%test;

%let wantreg = pacific;
%test;

option nomprint nomlogic nosymbolgen;
title;

[/pre]
N/A
Posts: 0