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

1) create table with one number

 

I used this code:


proc sql;
create table max_table as select
max(numeric_column) as max_column
from anydataset;
quit;

 

in this created table max_table  I have 1 column (max_column) with a certain number (likely between 1-20, it may vary each time run the code)

 

2) create macro variable with this value

data _NULL_;
set max_table ;
call symput('max_arr', max_column);
run;

 

3) set array with this value and I want to retain the values. This is my current version that works.


data test2;
set test;

array date_s{&max_arr};
retain date_s1-date_s16;

/*other code that does calculations for the array*/

run;

 

note that I put the 1-16 manually, because at the moment the array has 16 values (the max from the inital table was 16)

 

4) what I want is to make this dynamic, like the following (this does not work)

 

data test2;
set test;

array date_s{&max_arr};
retain date_s1-date_s&max_arr;

/*other code that does calculations for the array*/

run;


I hope my explanation of the problem is clear.

How can I make this dynamic?

1 ACCEPTED SOLUTION

Accepted Solutions
FreelanceReinh
Jade | Level 19

Hello @Jeroen_ING and welcome to the SAS Support Communities!

 

Unlike CALL SYMPUT, the newer CALL SYMPUTX routine removes leading blanks when a numeric value is assigned to a macro variable. Only these leading blanks must have been the reason why your RETAIN statement failed. So, you could just add the "X" after "SYMPUT".

 

But your code can be simplified in several ways:

  1. Steps 1 and 2 can be replaced by a single PROC SQL step using an INTO clause:
    proc sql noprint;
    select max(numeric_column) into :max_arr trimmed
    from anydataset;
    quit;
  2. The RETAIN statement accepts array names, so you don't need a variable list:
    retain date_s;
  3. Alternatively, you can specify one or more initial values in the ARRAY statement. This implies a RETAIN for all array elements. That is, you can omit the RETAIN statement if you specify something like
    array date_s{&max_arr} (&max_arr*.);

View solution in original post

3 REPLIES 3
FreelanceReinh
Jade | Level 19

Hello @Jeroen_ING and welcome to the SAS Support Communities!

 

Unlike CALL SYMPUT, the newer CALL SYMPUTX routine removes leading blanks when a numeric value is assigned to a macro variable. Only these leading blanks must have been the reason why your RETAIN statement failed. So, you could just add the "X" after "SYMPUT".

 

But your code can be simplified in several ways:

  1. Steps 1 and 2 can be replaced by a single PROC SQL step using an INTO clause:
    proc sql noprint;
    select max(numeric_column) into :max_arr trimmed
    from anydataset;
    quit;
  2. The RETAIN statement accepts array names, so you don't need a variable list:
    retain date_s;
  3. Alternatively, you can specify one or more initial values in the ARRAY statement. This implies a RETAIN for all array elements. That is, you can omit the RETAIN statement if you specify something like
    array date_s{&max_arr} (&max_arr*.);
ballardw
Super User

Step 4 may be extremely easy to accomplish if you have no other variables that start with the name of your array.

SAS provides a number of ways to create lists of variable. One of them is the : list which is the start of a variable followed by the : . That means "for this operation use all variables whose names start with the base".  And example with a data set you should have available.

 

data junk;
   set sashelp.class;
   array sss(10);
   retain sss: ;
   if _n_ le 10 then s[_n_] = weight;
run;

If you look at the output you can see for each of the first 10 records the weight is copied into one value then retained through the following iterations of the data step.

 

It is up to you to ensure that your array name does not start with the same characters or the other variables would be on the retain list and may result in unexpected output.

 

You may want to consider replacing your first two steps with :

proc sql noprint;
 select max(age) into : max_arr
  from sashelp.class;
quit;

The into : places the values of the select into a macro variable. Noprint means nothing gets printed to the results. I specifically said values because you can place multiple values into a single macro variable such as in this example:

proc sql noprint;
 select distinct age into : agelist separated by ' '
  from sashelp.class;
quit;

%put Age list is:&agelist;
Jeroen_ING
Calcite | Level 5

thanks, completely overlooked the fact that the space was causing the error.

I changed my code based on your improvements, thank you very much!!

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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
  • 3 replies
  • 911 views
  • 0 likes
  • 3 in conversation