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

Hi All,

About SYSNOBS automatic macro variable

SAS(R) 9.3 Macro Language: Reference

 

I dont understand that "Note: If the number of observations for the data set was not calculated by the previous procedure or DATA step, the value of SYSNOBS is set to -1."

What does this mean ?

Can i get any sample code ?

Thanks.

1 ACCEPTED SOLUTION

Accepted Solutions
Vince28_Statcan
Quartz | Level 8

Thanks DN

Well it appears my expectation based on documentation were miles off!

It appears to only consider the last output dataset despite the fact that it doesn't actually "read" that DS but only write it - it still reads its number of observations I guess.

Thus it behaves significantly closer to the &SQLOBS automatic macro than I expected.

data _null_; should always return 0.

@Amats, this explains why your data 1aa; run; empty data step returns 0 instead of 1. A file or dataset is actually created with 0 data records so the file was opened/closed and thus a number of observations output is retrieved.

If you reuse the _1 dataset defined above to compare with SQL, you will see the behavior is the same for empty queries.

953  proc sql;
954      select x
955      from _1
956      where x>3
957      ;
NOTE: No rows were selected.
958  quit;
NOTE: PROCEDURE SQL used (Total process time):
      real time           1.68 seconds
      cpu time            0.01 seconds


SYMBOLGEN:  Macro variable SQLOBS resolves to 0
959
960  %put &sqlobs;
0

So since it behaves on output and doesn't *seem to* care for input data that is read and for which a file was opened/closed through the step/procedure, I would assume that the reason your proc datasets had a value of &SYSNOBS=0 and not -1 is because the procedure itself is able to produce an output but since you did not use the out= option to output the results of the proc datasets to a file, the net number of records output is 0. That would allow to distinguish from, say, proc setinit; run; that are procedures without output that should result in a -1 code for &SYSNOBS (I couldn't think of any better documented procedure without output on the fly, sorry).

Sidethought: I wonder if it is possible to use symget immediately after a hash object .output method to see if it is updated then not that it is necessary, num_items method can achieve that anyway.

View solution in original post

9 REPLIES 9
kuridisanjeev
Quartz | Level 8

If Previous Procedure or Datastep failed to execute due to some errors,that time value of SYSOBS is set to -1.

Thanks,

Sanjeev.K

amats
Calcite | Level 5

Hi, Sanjeev.


I get the result "0" when running the below code.

Why it doesn't return "-1" ?

data 1aa;

run;

%put OBS=&sysnobs;

kuridisanjeev
Quartz | Level 8

Ahh i see,

I understand in that way,

Can you try writing Data _null_;run;,or just run Proc Datasets;run and check the value of the sysnobs?? I don't have SAS 9.3 access right now...

Thanks,

Sanjeev.K


amats
Calcite | Level 5

I tried all of your suggestions,

but it all returns "0"...

Vince28_Statcan
Quartz | Level 8

I don't have 9.3 on my current machine to test but from the description and my understanding of data step help wording conventions, I would assume it mimics the &SQLOBS with some limitations so if there is no SET statement in a data step, the value returned should be 0 as no the only dataset in an empty data step is that of the output but no observations are READ from the output datasets.

Similarly, I think proc datasets use VTABLES which are really only views and thus technically don't directly open a data set to read in the values. I'm not entirely sure why it doesn't output -1 though I'd have to get on a 9.4 test tower at work to run tests and someone else will likely provide a detailed answer before then but for data step functionalities, I suggest you test the following

data _1;

     x=1;

run;

%put &sysnobs; /* should be 0 if my understanding is correct */

data _2;

     x=1; output; x=2; output;

run;

%put &sysnobs; /* should be 0 as well */

data _1_2;

     set _1 _2;

run;

%put &sysnobs; /* should be either 2 or 3 depending if it considers the entire set statement entity as a single "opened dataset" */

/* create views for each _1 and _2 call them v_1 and v_2 for simplicity */

data _null_;

     set _1;

run;

%put &sysnobs; /* should be 1 */

data _null_;

     set v_1;

run;

%put &sysnobs; /* will likely be 0 that would explain the proc datasets results - if not, repeat with v_2 */

data _null_;

     set _2(where=(x=1));

run;

%put &sysnobs; /* should be 1 as technically where statements within the set statement are more efficient than where statements within the data step as it skips reading the record entirely */

With the above, it should give you insight on what to expect from various "usual" procedures but odds are you'd need to do tests on a per procedure basis to really understand how it works. In general, I would expect it to return the number of physical observations attached to the dataset tied to the DATA= statement for procedures that have that in their statement options.

ultimately, I suppose it's main use or purpose is to get the number of physical observations from sets located on a rdbms where you can't use nobs or nlobs from the sashelp.vtable to get the information.

data_null__
Jade | Level 19
17         GOPTIONS ACCESSIBLE;
18         data _1;
19              x=1;
20         run;

NOTE:
The data set WORK._1 has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time          
0.00 seconds
      cpu time           
0.01 seconds
     

21         %put NOTE:  &=sysnobs; /* should be 0 if my understanding is correct */
NOTE:  SYSNOBS=
1
22        
23         data _2;
24              x=1; output; x=2; output;
25         run;

NOTE:
The data set WORK._2 has 2 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time          
0.00 seconds
      cpu time           
0.01 seconds
     

26         %put NOTE:  &=sysnobs; /* should be 0 as well */
NOTE:  SYSNOBS=
2
27        
28         data _1_2;
29              set _1 _2;
30         run;

NOTE:
There were 1 observations read from the data set WORK._1.
NOTE: There were
2 observations read from the data set WORK._2.
NOTE: The data set WORK._1_2 has
3 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time          
0.00 seconds
      cpu time           
0.00 seconds
     

31         %put NOTE:  &=sysnobs; /* should be either 2 or 3 depending if it considers the entire set statement entity as a single
31       ! "opened dataset" */

NOTE:  SYSNOBS=
3
32        
33        
34         /* create views for each _1 and _2 call them v_1 and v_2 for simplicity */
35        
36         data v_1 / view=v_1;
37              set _1;
38         run;

NOTE:
DATA STEP view saved on file WORK.V_1.
NOTE: A stored DATA STEP view cannot run under a different operating
system.
NOTE: DATA statement used (Total process time):
      real time          
0.00 seconds
      cpu time           
0.00 seconds
     

39         %put NOTE:  &=sysnobs; /* should be 1 */
NOTE:  SYSNOBS=
1
40        
41         data _null_;
42              set v_1;
43         run;

NOTE:
View WORK.V_1.VIEW used (Total process time):
      real time          
0.00 seconds
      cpu time           
0.00 seconds
     
NOTE: There were
1 observations read from the data set WORK._1.
NOTE: There were
1 observations read from the data set WORK.V_1.
NOTE: DATA statement used (Total process time):
      real time          
0.00 seconds
      cpu time           
0.00 seconds
     

44         %put NOTE:  &=sysnobs; /* will likely be 0 that would explain the proc datasets results - if not, repeat with v_2 */
NOTE:  SYSNOBS=-
1
45        
46         data c;
47            set v_1;
48            run;

NOTE:
View WORK.V_1.VIEW used (Total process time):
      real time          
0.00 seconds
      cpu time           
0.00 seconds
     
NOTE: There were
1 observations read from the data set WORK._1.
NOTE: There were
1 observations read from the data set WORK.V_1.
NOTE: The data set WORK.C has
1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time          
0.00 seconds
      cpu time           
0.00 seconds
     


49         %put NOTE:  &=sysnobs; /* will likely be ? */
NOTE:  SYSNOBS=
1
50        
51        
52        
53         data _null_;
54              set _2(where=(x=1));
55         run;

NOTE:
There were 1 observations read from the data set WORK._2.
      WHERE x=
1;
NOTE:
DATA statement used (Total process time):
      real time          
0.00 seconds
      cpu time           
0.00 seconds
     

56        
57         %put NOTE:  &=sysnobs; /* should be 1 as technically where statements within the set statement are more efficient than
57       ! where statements within the data step as it skips reading the record entirely */

NOTE:  SYSNOBS=
2
58        
59        
60         GOPTIONS NOACCESSIBLE;
61         %LET _CLIENTTASKLABEL=;
62         %LET _CLIENTPROJECTPATH=;
63         %LET _CLIENTPROJECTNAME=;
64         %LET _SASPROGRAMFILE=;
65        
66         ;*';*";*/;quit;run;
67         ODS _ALL_ CLOSE;
68        
69        
70         QUIT; RUN;
71        
Vince28_Statcan
Quartz | Level 8

Thanks DN

Well it appears my expectation based on documentation were miles off!

It appears to only consider the last output dataset despite the fact that it doesn't actually "read" that DS but only write it - it still reads its number of observations I guess.

Thus it behaves significantly closer to the &SQLOBS automatic macro than I expected.

data _null_; should always return 0.

@Amats, this explains why your data 1aa; run; empty data step returns 0 instead of 1. A file or dataset is actually created with 0 data records so the file was opened/closed and thus a number of observations output is retrieved.

If you reuse the _1 dataset defined above to compare with SQL, you will see the behavior is the same for empty queries.

953  proc sql;
954      select x
955      from _1
956      where x>3
957      ;
NOTE: No rows were selected.
958  quit;
NOTE: PROCEDURE SQL used (Total process time):
      real time           1.68 seconds
      cpu time            0.01 seconds


SYMBOLGEN:  Macro variable SQLOBS resolves to 0
959
960  %put &sqlobs;
0

So since it behaves on output and doesn't *seem to* care for input data that is read and for which a file was opened/closed through the step/procedure, I would assume that the reason your proc datasets had a value of &SYSNOBS=0 and not -1 is because the procedure itself is able to produce an output but since you did not use the out= option to output the results of the proc datasets to a file, the net number of records output is 0. That would allow to distinguish from, say, proc setinit; run; that are procedures without output that should result in a -1 code for &SYSNOBS (I couldn't think of any better documented procedure without output on the fly, sorry).

Sidethought: I wonder if it is possible to use symget immediately after a hash object .output method to see if it is updated then not that it is necessary, num_items method can achieve that anyway.

data_null__
Jade | Level 19

The value after compiling a view is interesting.

26         data x; stop; run;

NOTE:
The data set WORK.X has 0 observations and 0 variables.

27         %put NOTE &=sysnobs;
NOTE SYSNOBS=0
28         data bv / view=bv;
29            set sashelp.class(obs=3) sashelp.class(obs=4);
30            run;

NOTE:
DATA STEP view saved on file WORK.BV.
NOTE: The original source statements cannot be     

31         %put NOTE &=sysnobs;
NOTE SYSNOBS=19
amats
Calcite | Level 5

Thank you all, I got it!

=====================================================================

p.s.

I get the following result,

I think, SYSNOBS doesn't seem affected by SETINIT procedure,

===Code1=====

data _1;

  x=1;

run;

proc setinit; run;

%put OBS=&sysnobs;

===Log======

OBS=1

===Code2=====

data _2;

  x=1;output; x=2;output;

run;

proc setinit; run;

%put OBS=&sysnobs;

===Log======

OBS=2

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

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
  • 9 replies
  • 5261 views
  • 5 likes
  • 4 in conversation