BookmarkSubscribeRSS Feed
keen_sas
Quartz | Level 8

I would like to prefix the dataset names for each variable present in the conditions to make it work logically in SQL joins by selecting the variables from the respective data set and assigning a alias name.Below are the examples of present requirement and the desired output

 

Have1: Gender = 'M' AND class= 'CHEMISTRY'
Want1: dsn.Gender='M' AND dsn.class='CHEMISTRY'

 

Have2: CAT = 'ADMINISTRATION' AND SUBCAT = 'ASSIST' AND department = 'Assistance' and OBJ = 'Event';
Want2: dsn.CAT = 'ADMINISTRATION' AND dsn.SUBCAT = 'ASSIST' AND dsn.department = 'Assistance' and dsn.OBJ = 'Event';

 

Have3: CAT = 'MEDICATIONS' and (BASAFL ='Y' or GLAFL ='Y' or DETFL ='Y' or NPHFL ='Y');
Want3: dsn.CAT = 'MEDICATIONS' and (dsn.BASAFL ='Y' or dsn.GLAFL ='Y' or dsn.DETFL ='Y' or dsn.NPHFL ='Y');


The conditions may vary and the number of variables unknown for each condition.Assuming all these conditions and variables from a single data set for time being. Any help is greatly appreciated.

6 REPLIES 6
ErikLund_Jensen
Rhodochrosite | Level 12

Hi keen_sas

It is not clear to me what you are trying to achieve. Could you describe your problem with more details, such as example input data set, example sql step and a example output data set? - and also a short explanation of why you want to do it. It is easier to come up with suggestions if one knows the ideas behind the problem.

keen_sas
Quartz | Level 8

Hi Jensen,


I am reading these conditions (described in HAVE) from excel sheet and converting the condition into macro variables and using this in where condition in proc sql join as below

 

proc sql;
create table abc as select ab.* ,ac.OCCUR as occur_ from abc as ab
left join
lib.dd as dd on ab.CID=dd.CID
Gender='M' AND class='CHEMISTRY';
quit;

 

In  excel the condition is given as below , but i want to add the data set/alias name while passing this in WHERE condition
Have1: Gender = 'M' AND class= 'CHEMISTRY'

The variables present in where condition may be present in both of the datasets, so to avoid that issue i want to concatenate dataset/alias name to that condition and convert into macro variable to use that in where condition.

Want1: dsn.Gender='M' AND dsn.class='CHEMISTRY'

 

proc sql;
create table abc as select ab.* ,ac.OCCUR as occur_ from abc as ab
left join
lib.dd as dd on ab.CID=dd.CID
AB.Gender='M' AND AB.class='CHEMISTRY';
quit;

 

Dataset values as below

 

Have1 Want
Gender='M' AND class='CHEMISTRY'; dsn.Gender='M' AND dsn.class='CHEMISTRY'
ErikLund_Jensen
Rhodochrosite | Level 12

hi keen_sas

 

I think the following code could be used as a starting point. It makes the required translation from a macro variable and returns the result in another,


%let alias = dsn;
%*let condition = Gender='M' AND class='CHEMISTRY';
%*let condition = CAT = 'ADMINISTRATION' AND SUBCAT = 'ASSIST' AND department = 'Assistance' and OBJ = 'Event';
%let condition = CAT = 'MEDICATIONS' and (BASAFL ='Y' or GLAFL ='Y' or DETFL ='Y' or NPHFL ='Y');

data _null_; set conditions;
	length extcondition $255;
	length word nextword $60;

	* make sure everything is separated with one blank;
	condition = "&condition";
	condition = tranwrd(condition,'=',' = ');
	condition = tranwrd(condition,'(',' ( ');
	condition = tranwrd(condition,')',' ) ');
	condition = left(compbl(condition));
	
	* loop over every single item and build new condition;
	* - if next item is '=' then precede item with dsn;
	items = countw(condition,' ');
	do i = 1 to items;
		word = scan(condition,i,' ');		
		if i < items then nextword = scan(condition,i+1,' ');
		if nextword = '=' then 
			extcondition = catx(' ', extcondition, "&alias.."||scan(condition,i,' '));
		else extcondition = catx(' ', extcondition, scan(condition,i,' '));
	end;
	call symput('extcondition',extcondition);
run;
%put &=extcondition;

but so far only with one alias supplied in another macro variable.

Tom
Super User Tom
Super User

You could ask PROC SQL to translate it for you.

Look at this sample program using SASHELP.CLASS as the input dataset.

filename code temp;
options nosource nonotes obs=0;
proc printto log=code new ; run;
proc sql feedback ;
select name,age from sashelp.class dsn ;
quit;
proc printto log=log; run;
options notes source obs=max;

Let's see what PROC SQL generated to the LOG file.

9    filename code temp;
10   options nosource nonotes ;
17   filename code temp;
18   options nosource nonotes obs=0;
25
26   data _null_;
27    infile code;
28    input;
29    put _infile_;
30   run;

NOTE: The infile CODE is:
      Filename=.../#LN00021,
      Owner Name=...,Group Name=...,
      Access Permission=-rw-rw-r--,
      Last Modified=27Jan2019:13:40:38,
      File Size (bytes)=69


        select DSN.Name, DSN.Age
          from SASHELP.CLASS DSN;
NOTE: 4 records were read from the infile CODE.
      The minimum record length was 0.
      The maximum record length was 33.
NOTE: DATA statement used (Total process time):
      real time           0.21 seconds
      cpu time            0.01 seconds

So SQL converted this:

select name,age from sashelp.class dsn ;

to this:

       select DSN.Name, DSN.Age
          from SASHELP.CLASS DSN;
keen_sas
Quartz | Level 8

Thank you Jenssen and Tom for your solutions.

 

I think the SQL code is helping to determine the DSN, but in my condition i have to concatenate the DSN to variable name after identifying the DSN from excel sheet. Any other easier method in SQL for concatenation.

 

Thanks for your responses to move forward.

 

Tom
Super User Tom
Super User

To do what you are really asking you would need to create a SAS language parser.  Probably not something that you want try to figure out.

 

Why not just include the prefix in the source code to begin with?

 

So your snippets of code will look like:

XXX.age > 10 or XXX.gender = 'F'

Then your metadata (Excel is NOT a good system to use to store data by the way.  It is a spreadsheet, not a database.) might have something that says for alias XXX you want to use the actual dataset (aka Table) named MyData.  So then your final generated code might look like:

select * 
from MyData XXX
where XXX.age > 10 or XXX.gender = 'F'
;

No editing of the code snippets is needed at all.

 

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 6 replies
  • 1634 views
  • 0 likes
  • 3 in conversation