LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous (more recent) messageNext (less recent) messagePrevious (more recent) in topicNext (less recent) in topicPrevious (more recent) by same authorNext (less recent) by same authorPrevious page (February 1998, week 4)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Tue, 24 Feb 1998 09:46:20 -0500
Reply-To:     WHITLOI1 <whitloi1@WESTAT.COM>
Sender:       "SAS(r) Discussion" <SAS-L@UGA.CC.UGA.EDU>
From:         WHITLOI1 <whitloi1@WESTAT.COM>
Subject:      Re: SAS data views
Comments: To: Grace La Torra <grace@NMSU.EDU>
Comments: cc: Allan Page <pageal@TOTAL.NET>

Subject: SAS data views Summary: An inconsistency in WHERE processing is revealed and used to provide a stable solution to using execution time resolution of macro variables in the WHERE statement of a data view. Respondent: Ian Whitlock <whitloi1@westat.com>

Grace La Torra <grace@NMSU.EDU> asked:

>I am creating a view of a data set using the following code: > >data stuall.persv / view = stuall.persv; >set stuall.personal; >by ssn semnum; >where semnum <= &perssem; >if last.ssn then output; >run; > >I am trying to build a view that will change depending on the macro >variable &perssem. In other words, when perssem is set to 60 the view >will be different from when perssem is set to 64. The kicker here is >that I don't want the macro variable to be resolved when the view is >created, but when the view is accessed. > >Does anybody have any words of wisdom?

In the past I have simply answered

data view / view = view ; set indata ; where invar = symget ( 'macvar' ) ; /* other processing code */ run ;

Imagine my surprise when Allan Page <pageal@TOTAL.NET> responded (in part):

>The value in the where clause is set at the time the view is >created.

Each test I have run in the past has shown the above to be a valid solution. SYMGET should get the value of the macro variable at execution time, hence it should be a perfectly good solution. Now I find that it is an unstable solution! The question is - is symget ( 'macvar' ) a constant? For me, it certainly is not, since the value of MACVAR can in principle change at any time. However, SAS takes the point of view that the expression 'MACVAR' is constant and that if MACVAR already exists then SYMGET ( 'MACVAR' ) must also be constant. In this case SAS does the evaluation during the compile of the view step instead of during its execution.

Why did past testing not find a problem? I have always been careful to choose a nonexistent macro variable and place the assignment of the macro variable after the view step. In this case SAS cannot perform the evaluation during the compile of the step; hence it is left to the execution phase where it belongs. Now what happens if the code is executed a second time (say interactively)? For the second execution the macro variable now exists; hence the definition of the view changes because the expression is now evaluated at compile time instead of the intended execution time.

One might hope that the problem lies in the use of a view and not in the WHERE processing itself. But the following log dashes that grasping at straws.

1 data w ; 2 do x = 1 to 3 ; 3 output ; 4 end ; 5 run ;

NOTE: The data set WORK.W has 3 observations and 1 variables. NOTE: The DATA statement used 0.59 seconds.

6 7 %let macvar = 1 ; 8 data _null_ ; 9 set w ; 10 where put ( x , 1. ) = symget ( 'macvar' ) ; 11 call symput ( 'macvar' , '3' ) ; 12 put x= ; 13 run ;

X=1 NOTE: The DATA statement used 0.11 seconds.

In contrast to the way SYMGET is handled, consider the statement

where ranuni ( 96943 ) < .1 ;

Here 96943 is a constant but SI was wise enough to realize that is represents a changing seed; hence is should be (and is) evaluated at execution time rather than compile time.

Now what about the macro variable problem? Well there is a second chance to get it right because RESOLVE like SYMGET should obtain macro variables at execution time. Here SI got it right as shown by

37 %let macvar = 1 ; 38 data _null_ ; 39 set w ; 40 where put ( x , 1. ) = resolve ( '&macvar' ) ; 41 call symput ( 'macvar' , '3' ) ; 42 put x= ; 43 run ;

X=1 X=3 NOTE: The DATA statement used 0.0 seconds.

Perhaps the moral is that SYMGET should be considered for historical purposes only.

Ian Whitlock


Back to: Top of message | Previous page | Main SAS-L page