SAS: execute sql query strings out of a table?

喜欢而已 提交于 2021-02-11 13:25:42

问题


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. A Proc 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 variable
  • symget, 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!