The discussion of unexpected evaluation results is for code run in SAS 9.4 TS1M4 on Windows 10.0.17763 Build 17763.
3 proc options;
4 run;
SAS (r) Proprietary Software Release 9.4 TS1M4
SQL does not have a missing value (., .<letter>) concept in the same way DATA Step and other Procs do. SQL has NULL and SAS coerces missing values into NULL, so there is a fuzzy edge and you found a problem there !
The failure to properly evaluate an expression appears to be how 9.4 SQL implementation is processing literal missing (.) values in this specific case. The failure is not in the IFN, but rather the evaluation passed to IFN !
Examining only the logic expression the problems does not seem to be related to IN. Similar unexpected evaluation results occur when the IN is split into a series of ORs. The specific causation appears to be where the missing literal (.) appears in the expression -- which in turn becomes 9.4 SQL implementation innards (parsing, etc.)
Definitely seems to be a bug when more than two sub-expressions and one of them uses a missing (.). The proper remedy, and one that becomes more suitable for remote or pass-through processing, would be to avoid using missing literals (.) in your SQL and use ANSI null tests operators IS NULL and IS NOT NULL
data have;
b = 9.1;
run;
proc sql;
create table want as
select
b
, b in (.,0) | b > 100 as part1 /* correct result */
, b in (.,0) | b < 1 as part2 /* correct result */
, b > 100 | b < 1 as part3 /* correct result */
, b in (.,0) | b > 100 | b < 1 as parts_null_first /* INCORRECT result */
, b > 100 | b < 1 | b in (.,0) as parts_null_last /* INCORRECT result */
, b=. | b=0 | b > 100 | b < 1 as parts_no_in_null_first /* INCORRECT result */
, b=0 | b > 100 | b < 1 | b= . as parts_no_in_null_last /* correct - weird? */
, b is null | b=0 | b > 100 | b < 1 as parts_is_null /* correct result */
, calculated part1 | calculated part2 | calculated part3 as calc_parts_in_1_expr /* correct result */
from have
;
quit;
I didn't test if the same issue occurs when the problematic expression is in a WHERE caluse. The expression is not a problem as an assignment in DATA step:
data want2;
set have;
parts_null_first = b in (.,0) | b > 100 | b < 1 ; /* correct result */
parts_null_last = b > 100 | b < 1 | b in (.,0); /* correct result */
run;
If the expression evaluation 'error' occurs in where expressions, then the where evaluation engine is more likely the root cause -- I believe the same engine is used for Proc/Data WHERE statements, Dataset WHERE= option and SQL evaluations.
There might be a SAS Note or Hotfix for the situation but I didn't go looking.
Another discussion of testing for missing values can be found in SAS_Tipster's "SAS Tip: Use IS MISSING and IS NULL with Numeric or Character Variables" on communities.sas.com. The important take away is the use of operators in criteria testing for null values.
The IS MISSING and IS NULL operators, which are used with a WHERE statement, can handle character or numeric variables. They also work with the NOT operator:
Documentation summarizes IS MISSING predicate as:
Tests for a SAS missing value in a SAS native data store.
proc options option = missing; run;and check the value displayed in the log. - Amirifn(condition,1,0)with justconditionand SAS will still generate 1 for true and 0 for false.. - Tomsysvlong= 9.04.01M5P091317. - Tom