Calling macro inside PROC SQL in SAS - sas

I need to call a macro code from proc sql in SAS like below.
PROC SQL;
CONNECT TO DB2 (SSID = &DGSYS);
CREATE TABLE <DS_NAME> AS
SELECT * FROM CONNECTION TO DB2
(
SELECT * FROM <TAB_NAME> WHERE...
);
%MACRO_CODE(....) --> am calling a macro block of code here
DISCONNECT FROM DB2;
QUIT;
But this is throwing up an error. Could this not be done?
When I used a macro variable in my query it is allowing me but not a call made to macro code.
The macro would create another macro variable which will be an IN CLAUSE holding values from the previously created table/dataset. And it would be subsequently used in the another CREATE TABLE... in side the same PROC SQL.

If I understand correctly, it sounds like a macro isn't necessary for what you're doing. If you're creating a macro variable containing a list of values from a dataset, you can just use the INTO: clause.
ds_name : Table with numeric and alphanumeric variables.
proc sql noprint;
/* If VAR_NAME is numeric, this works */
select distinct var_name
into: listvals
separated by " "
from ds_name;
/* If VAR_NAME is character, do this instead */
select distinct cats("'",varname,"'")
into: listvals
separated by " "
from ds_name;
create table new_ds as
select *
from another_ds
where var_name in (&listvals);
quit;
I hope that helps.

Related

Issue with proc sql to select large number of files

I am trying to select a large number of files using the proc sql statement below
proc sql;
select cats(libname, ".",memname) into :names separated by " "
from dictionary.tables
where upcase(libname) = "MYLIBNAME";
quit;
but when I write %PUT Data sets: &names; nothing appears in the log file and I get an error saying the macro names is not resolved. Any ideas what is going wrong here?
MYLIBNAME is an invalid libref. Librefs have a maximum of 8 characters. MYLIBNAME is 9 characters so there will be no librefs defined in your SAS session that can match it.
What happens if you try libname = "WORK" or libname = "SASHELP" ? Macro variable names will get populated.
Be careful with libraries containing many thousands of tables. A macro variable can only be 64K-2 characters long.
#Richard answer is perfect. if it is still not working do the following.
try outobs =1, just to check with and without where clause
proc sql outobs= 1;
select cats(libname, ".",memname) into :names separated by " "
from dictionary.tables
where upcase(libname) = "SASHELP";
quit;
%put &names;
use proc contents, followed by concatenation. it will show error in next step, if your macro variable is longer than 65534
PROC CONTENTS DATA=SASHELP._ALL_ out= new(keep=memname libname) noprint; RUN
proc sql;
select cats(libname, ".",memname) into :names separated by " "
from new;

Extract Variables with matching condition in SAS [duplicate]

I hope someone can help. I have a large dataset imported to SAS with thousands of variables. I want to create a new dataset by extracting variables that have a specific keyword in their name. For example, the following variables are in my dataset:
AAYAN_KK_Equity_Ask
AAYAN_KK_Equity_Bid
AAYAN_KK_Equity_Close
AAYAN_KK_Equity_Date
AAYAN_KK_Equity_Volume
AAYANRE_KK_Equity_Ask
AAYANRE_KK_Equity_Bid
AAYANRE_KK_Equity_Close
AAYANRE_KK_Equity_Date
I want to extract variables that end with _Ask and _Bid without knowing the rest of the variable's name. Is there a way to do that? I want to try using a do loop but don't know how to instruct SAS to compare each variable's last part of the name with _Ask or _Bid.
Afterwords. I want to create a new variable for each set that starts with full name of the variable except the last part (Which is _Ask or _Bid). Can I do that in using an assignment statement?
You probably want to query sashelp.vtable which holds the metadata about your data set. Assuming your data is in the library WORK and called TABLE the following creates a list of the variables that end in ASK.
proc sql;
select name into :varlist separated by " "
from sashelp.vcolumn
where libname="WORK" and memname="TABLE" and upcase(name) like '%_ASK';
quit;
*To rename the variables with MID generate a rename statement;
proc sql;
select catx("=", name, tranwrd(upcase(name), "_ASK", "_MID"))
into :rename_list separated by " "
from sashelp.vcolumn
where libname="WORK" and memname="TABLE" and upcase(name) like '%_ASK';
quit;
%put &rename_list;
data want_ask;
set work.table
(keep = &varlist);
rename &rename_list;
run;

Using date macro variable in PROC SQL

I am having trouble getting a macro variable to work correctly in PROC SQL and it doesn't make sense to me.
First, if I generate a query like this:
PROC SQL;
SELECT
a.*
,'31MAR2016' As EVAL_DATE format=date09.
FROM
myTable a
;
it works as expected and puts a date field at the end of the table.
Then, if I do this:
%Let testDate = '31MAR2016'd;
%put &testDate;
PROC SQL;
SELECT
a.*
,&testDate As EVAL_DATE format=date09.
FROM
myTable a
;
this again runs properly, with the log window showing the value of:
'31MAR2016'd
But, if I do this:
%Let Eval_Date = %sysfunc(intnx (month,%sysfunc(inputn(201603,yymmn6.)) ,0,E),date09.);
%Let Eval_date_test = %str(%')&Eval_Date.%str(%')d;
%Put Eval_date_test;
PROC SQL;
SELECT
a.*
,&Eval_date_test As EVAL_DATE format=date09.
FROM
myTable a
;
SAS stops running with the error;
"ERROR 22-322: Syntax error, expecting one of the following: a name, a quoted string, a numeric constant, a datetime constant,
a missing value, (, *, +, -, BTRIM, CALCULATED, CASE, EXISTS, INPUT, NOT, PUT, SUBSTRING, TRANSLATE, USER, ^, ~.
ERROR 200-322: The symbol is not recognized and will be ignored."
The log displays the value of &Eval_date_test to be the same '31MAR2016'd as it was in the second example. Note that I created the variable in two steps for clarity, but the same thing happens if you create it in one step.
In case it matters, I am running SAS Enterprise Guide 6.1
Why doesn't this work?
This has to do with how the macro is being dereferenced with the %str() macro. Try the %unquote() macro:
PROC SQL;
SELECT
a.*
, %unquote(&Eval_date_test) As EVAL_DATE format=date09.
FROM
sashelp.cars a
;
quit;
http://support.sas.com/documentation/cdl/en/mcrolref/67912/HTML/default/viewer.htm#p1f5qisx8mv9ygn1dikmgba1lmmu.htm
You are working much too hard and just confusing poor old SAS. Instead of using macro quoting just use the right quote characters to begin with. SAS doesn't care which quote characters you use, but text inside of single quotes is not evaluated for macro triggers and text inside of double quotes is. So '&eval_date'd does not resolve the macro variable reference and "&eval_date"d does.
%let Eval_Date="%sysfunc(intnx(month,%sysfunc(inputn(201603,yymmn6)),0,E),date9)"d;
You're missing a comma after a.*

Reading a list of name to a SAS Macro

I am trying to read a list of values into a macro, so that the macro variable would contain the table name and create a column that would contain the table name.
My attempt, which is wrong, was trying to use the code below, and erroring out because of the line " '&tbl' as Table_Dt ". The code below is inefficient, so feel free to enhance it. Thanks for your help.
%macro flat(tbl);
proc sql exec feedback stimer noprint outobs=5;
CREATE TABLE &tbl as
SELECT
ID,
DOB,
'&tbl' as Table_Dt
FROM &tbl..flat_file;
QUIT;
%mend flat;
%flat(flat0113);
%flat(flat0213);
...
%flat(flat1213);
As you are basically processing a list, this could also be done using call execute. No need to write all the information to macro variables. All tables/libraries are already stored in the sashelp tables and therefore are ready for list processing.
data _null_;
set sashelp.vslib (where=(substr(libname,1,4) = 'FLAT')) end =eof;
if _n_ = 1 then call execute ('proc sql exec feedback stimer noprint outobs=5;');
call execute ('
CREATE TABLE '|| libname ||' AS
SELECT ID,
DOB,
"'||compress(libname)||'" as Table_Dt
FROM '||compress(libname)||'.flat_file
;
');
if eof then call execute ('QUIT;');
run;
Macros in quotation marks will only resolve with double quotes, not single. If you want to do a more efficient way, you can do so with the following modified code. I am assuming that you are reading from libraries named flat0113, flat0213, etc.
Step 1: Get a list of all the libnames with the word "flat" in it
proc sql noprint;
select distinct libname
, count(libname)
into: tbl_list separated by ' '
, total_tbls
from sashelp.vmember
where libname LIKE 'FLAT%'
;
quit;
This will create two macro variables: &tbl_list, and &total_tbls.
&tbl_list holds the values flat0113 flat0213 flat ... flat1213.
&total_tbls holds the total number of values in &tbl_list.
Step 2: Loop through the newly created list
%macro readTables;
%do i = 1 %to &total_tbls;
%let tbl = %scan(tbl_list, &i);
proc sql exec feedback stimer noprint outobs=5;
CREATE TABLE &tbl as
SELECT
ID,
DOB,
"&tbl" as Table_Dt
FROM &tbl..flat_file;
quit;
%end;
%mend;
%readTables;
This will read each individual value from &tbl_list one by one until the very end of the list.

Subsetting a dataset by selecting variables based on keywords in their name in SAS

I hope someone can help. I have a large dataset imported to SAS with thousands of variables. I want to create a new dataset by extracting variables that have a specific keyword in their name. For example, the following variables are in my dataset:
AAYAN_KK_Equity_Ask
AAYAN_KK_Equity_Bid
AAYAN_KK_Equity_Close
AAYAN_KK_Equity_Date
AAYAN_KK_Equity_Volume
AAYANRE_KK_Equity_Ask
AAYANRE_KK_Equity_Bid
AAYANRE_KK_Equity_Close
AAYANRE_KK_Equity_Date
I want to extract variables that end with _Ask and _Bid without knowing the rest of the variable's name. Is there a way to do that? I want to try using a do loop but don't know how to instruct SAS to compare each variable's last part of the name with _Ask or _Bid.
Afterwords. I want to create a new variable for each set that starts with full name of the variable except the last part (Which is _Ask or _Bid). Can I do that in using an assignment statement?
You probably want to query sashelp.vtable which holds the metadata about your data set. Assuming your data is in the library WORK and called TABLE the following creates a list of the variables that end in ASK.
proc sql;
select name into :varlist separated by " "
from sashelp.vcolumn
where libname="WORK" and memname="TABLE" and upcase(name) like '%_ASK';
quit;
*To rename the variables with MID generate a rename statement;
proc sql;
select catx("=", name, tranwrd(upcase(name), "_ASK", "_MID"))
into :rename_list separated by " "
from sashelp.vcolumn
where libname="WORK" and memname="TABLE" and upcase(name) like '%_ASK';
quit;
%put &rename_list;
data want_ask;
set work.table
(keep = &varlist);
rename &rename_list;
run;