问题
If I have a table containing sql query strings like this (column query
)
id query n
——————————————————————————————-—————————————
1 select count(*) from tab where x=...
2 select count(*) from tab where x=...
...
In SAS is there a way to save the results of these queries in another column n
?
回答1:
Just for fun - an approach using only proc sql:
data queries;
input id :8. query :$100.;
infile datalines dsd;
datalines;
1,select count(*) as count from sashelp.class where sex = 'F'
2,select count(*) as count from sashelp.class where sex = 'M'
;
run;
proc sql noprint;
select catx(' ','select ', id, ' as id,', substr(query, 7)) into :code
separated by ' union all '
from queries;
create table want as
&code;
quit;
This will only work as long as the total combined length of all your queries fits within the maximum allowed length of a single macro variable. If in doubt, check the value of the MVARSIZE system option.
回答2:
You should be able to do this by calling a macro within a data step, but depending on how the query is written, you'll have to call it in a sub-query in proc sql
.
%macro run_query(q,id);
/* This section expects that your original query assigns the alias 'count' to the result value */
proc sql noprint;
select count into: count * This assigns the result count into a macro variable count;
from (
&q.) a;
quit;
data want;
set want;
if id=&id. then result = &count.;
run;
%mend;
At this point we have the macro run_query
which takes the query, and id as inputs. Next, we will copy the dataset and then iterate through the original dataset updating each result based on the id
.
data want;
set have;
run;
data _null_;
set have;
call execute(%nrstr(%run_query('||query||','||id||'))');
run;
回答3:
If all the queries have a result set of one row & one column, you are dealing with a scalar result which can be placed in a data set variable.
Interaction features to use:
dosubl
, execute a separate SAS code block while a STEP is running. AProc SQL
query in this case.The DOSUBL function enables the immediate execution of SAS code...
DOSUBL executes code in a different SAS executive (known as a side session)
into :macro-variable
, store result in a macro variablesymget
, retrieve result from macro environment
If you are querying the same native SAS table over and over again, you might consider including:
sasfile
, opening the data set into memory so disk i/o occurs only once when querying the table repeatedly
Example
The queries, as stated in the question, do NOT include an INTO
clause. On the presumption that each query does not have INTO
AND has a single scalar result, the INTO
clause can be introduced into the query string via TRANWRD
.
data have;
input;
query = _infile_;
datalines;
select count(*) from sashelp.class where name between 'A' and 'F'
select count(*) from sashelp.class where name between 'F' and 'K'
select count(*) from sashelp.class where name between 'K' and 'O'
select count(*) from sashelp.class where name between 'O' and 'S'
select count(*) from sashelp.class where name between 'S' and 'ZZ'
select count(*) from sashelp.class where name between 'A' and 'K'
select count(*) from sashelp.class where name between 'A' and 'O'
select count(*) from sashelp.class where name between 'A' and 'S'
select count(*) from sashelp.class where name between 'A' and 'ZZ'
;
sasfile sashelp.class open;
data want;
set have;
* tweak 'presumed to be scalar' query;
length into_query $1000; drop into_query;
into_query = tranwrd (query, 'from', 'into :scalar_result from');
rc = dosubl('proc sql noprint; ' || into_query);
query_result = symget('scalar_result');
run;
sasfile sashelp.class close;
ods listing; proc print; run;
have
proc print
query_
Obs query rc result
1 select count(*) from sashelp.class where name between 'A' and 'F' 0 4
2 select count(*) from sashelp.class where name between 'F' and 'K' 0 8
3 select count(*) from sashelp.class where name between 'K' and 'O' 0 2
4 select count(*) from sashelp.class where name between 'O' and 'S' 0 3
5 select count(*) from sashelp.class where name between 'S' and 'ZZ' 0 2
6 select count(*) from sashelp.class where name between 'A' and 'K' 0 12
7 select count(*) from sashelp.class where name between 'A' and 'O' 0 14
8 select count(*) from sashelp.class where name between 'A' and 'S' 0 17
9 select count(*) from sashelp.class where name between 'A' and 'ZZ' 0 19
来源:https://stackoverflow.com/questions/60158117/sas-execute-sql-query-strings-out-of-a-table