SAS SQL create table depending on macro variable result - sql

I am struggling with creating a new table in proc sql SAS depending on macro variable result.
1) I want to check if necessary table exists.
2) If it exists then I want to create a new table with given parameters.
3) If it doesn't exist I want to create a new table with different parameters.
I think I know how to check if table exists (0 or 1 in log results):
%let tex1 = %sysfunc(exist(Base.pk_&monthP1));
%put tex1 = &tex1.;
But I do not know how to implement this result into proc sql statement.
I need sth like this:
proc sql;
create table test as
select case when &text1 = 0 then select ...
else
select ...
end ;
quit;
Thank you in advance for suggested solutions.

So if both tables have the same structure then the only part of the SQL code that needs to change is the FROM clause. It is probably easier to conditionally set a macro variable to the name to use and replace the name of the dataset with a reference to the macro variable.
select var1,varb, ....
from &dsname.
Now the problem becomes one of just setting the macro variable. You could do that with macro logic. But you could also just do that with data step logic.
data _null_ ;
if exist("Base.pk_&monthP1") then call symputx('dsname','table1');
else call symputx('dsname','table2');
run;
proc sql;
... from &dsname. ...

Related

Is there a way to nest a sql statement in a SAS IF/THEN/DO function?

So I have a SAS job that is scheduled to run and update a table regularly. I'm trying to add a functionality that drops the oldest month from the table when it is updating on the first day of a new month. Right now it looks like this:
PROC sql;
create table DropOldMonth as
select *
from ret.ServiceGFR_Impact;
create table DropOldMonth2 as
select *
from DropOldMonth
where date <> 'Jan 2020';
data _null_;
IF FirstDayofMonth = &todaysDate THEN DO;
proc sql;
drop table ret.ServiceGFR_Impact;
data ret.ServiceGFR_Impact;
set work.DropOldMonth2;
END;
run;
But I get this error:
ERROR 117-185: There was 1 unclosed DO block.
right below the Proc sql statement. I assume it's because there's a proc sql statement before and END statement to the DO function. However I need it to drop that table when that IF condition is true.
You may want to edit it in place instead of dropping it:
data ret.ServiceGFR_Impact;
set ret.ServiceGFR_Impact;
where date <> 'Jan 2020';
run;
make sure you have a backup before running it

Storing results of a stored procedure in a Google Big Query table

Here is a link to the question I asked earlier. The accepted answer works perfectly.
But this stored procedure processes 2 statements and after running this procedure I have to click on View Results of the second statement to see the result in Google Big Query. Is there a way to save the results in some table automatically using the 'Query Settings' in Google Big Query and specifying the name of the table I want to store the results in?
You cannot set a destination table for a script (or for call a procedure), instead, you can convert your SELECT statement into CREATE TABLE ... AS SELECT, for example:
SELECT 1 x;
=>
CREATE TABLE myDataset.myTable
AS SELECT 1 x;
You can define a string parameter for your procedure. Then use this parameter in the dynamic query to write the results to the table.
CREATE OR REPLACE PROCEDURE `my_dataset.my_procedure`(destination_table STRING)
BEGIN
CREATE TEMP TABLE tmp AS SELECT 1 x;
EXECUTE IMMEDIATE (
FORMAT("CREATE OR REPLACE TABLE `%s` AS SELECT * FROM tmp", destination_table));
END
Now you can provide a table name and call this procedure to write the results to the table.
CALL `my_dataset.my_procedure`("my_dataset.my_table");
SELECT * FROM `my_dataset.my_table`

How to insert partial source code in SAS?

My data is a SAS Table with 50k rows and 300 columns.
Here I make a little example with only 10 columns. Let's say that 3 colums are refecence and the other are variable columns.
Here is my SAS programm:
PROC SQL;
CREATE TABLE WORK.MATRIX(label="MATRIX with variable columns") AS
SELECT t1.REFERENCE_1,
t1.REFERENCE_2,
t1.REFERENCE_3,
t1.COLUMN_A,
t1.COLUMN_B,
t1.COLUMN_C,
t1.COLUMN_D,
t1.COLUMN_E,
t1.COLUMN_F,
t1.COLUMN_G
-------
Variable souce code which makes operation on these columns
-------
FROM WORK.MY_DATA t1;
QUIT;
I alreary have a SAS code that gives me source code for a given choice of columns. Here is the output of my SAS code:
t1.COLUMN_B,
t1.COLUMN_D,
t1.COLUMN_G,
I can now store this code here „c:\My_columns_choice.txt“.
This is what I would like to have:
PROC SQL;
CREATE TABLE WORK.MATRIX(label="MATRIX with variable columns") AS
SELECT t1.REFERENCE_1,
t1.REFERENCE_2,
t1.REFERENCE_3,
INSERT „c:\My_columns_choice.txt“
INSERT „c:\My_source_code_which_makes_operations.txt“
FROM WORK.MY_DATA t1;
QUIT;
So the question arises as follow, is this possible to insert partial source code in SAS programm through a sort of function like INSERT?
What is the correct syntax?
Many thanks.
Cheers
Mauri
You can use %INCLUDE to include multiple lines of code, but you cannot use that to include parts of a statement. But you can use a macro variable to generate code that could be just part of a statement. For example you could make a macro variable that has a comma separated list of column references.
%let varlist=t1.COLUMN_B,t1.COLUMN_D,t1.COLUMN_G;
Then you can reference the macro variable where you want to insert the text.
PROC SQL;
CREATE TABLE MATRIX(label="MATRIX with variable columns") AS
SELECT t1.REFERENCE_1
, t1.REFERENCE_2
, t1.REFERENCE_3
, &varlist
FROM MY_DATA t1
;
QUIT;
If you want to store this in a file you could either store it in the form or the %LET statement above and then just use %INCLUDE to run it in advance of your SQL statement so that the macro variable exists. Note that your file would then need to include full SAS statements and not just a part of a statement.
Or you could write a DATA step (or other code) to read the text file into the macro variable. The advantage of using a DATA step to read the file is then the file can contain only part of a statement. For example here is a simple data step to read in a one line file and store it in a macro variable.
data _null_;
infile 'column_list.txt' ;
input;
call symputx('VARLIST',_infile_);
run;
proc sql;
... &varlist ...
Use %INCLUDE macro statement. Add SOURCE2 option to obtain a log.
%INCLUDE 'c:\My_source_code_which_makes_operations.txt' / SOURCE2;
EDIT:
%include is NOT a macro statement, so in this special case (proc sql) it doesn't work. Only you can include the whole query, but a part of it is not acceptable.
To solve this problem you can read file using data step and create a macro variable, wich you put in select statement.
Example (only one line in text file):
filename f "/folders/myfolders/class.txt";
data _null_;
infile f dlm='00'x lrecl=32767;
length line $32767;
input line;
call symputx('vars', line);
run;
PROC SQL;
CREATE TABLE class AS
SELECT name,
&vars
FROM sashelp.class;
QUIT;

how to append all tables with their table name in SAS

I'm trying to append all the tables(same structure) in the work library into one data set. But I need to have a new column name which can indicate the table name.
I tried two methods:
macro array and do over:
PROC APPEND BASE=_dupout DATA=dup_&dataset. FORCE;
RUN;
Proc SQL:
PROC SQL;
SELECT MEMNAME, catx('.', libname, MEMNAME) INTO : MEMNAMES SEPARATED BY ' '
from dictionary.tables
where libname='WORK';
quit;
DATA DUP_OUT;
SET &MEMNAMES.;
RUN;
but neither of those I can find a way add a new column (table name). Maybe it is a very simple question? I'm stuck..please help...
Very close, use the INDSNAME option in your SET statement.
DATA DUP_OUT;
SET &MEMNAMES. INDSNAME=SOURCE;
DSET=SOURCE;
RUN;

Update an oracle table with data from another table in SAS

I am trying to run the following piece of code to update table summary from data in click_summ table.
data temp(index=(comp=(card_number package_sk)));
set click_summ(where=(^missing(e_1st_click_dt)));
keep card_number package_sk e_1st_click_dt;
run;
data summary(drop=new_date) ;
set summary;
set temp(rename=(e_1st_click_dt= new_date) in=a) key=comp;
if a then do;
e_1st_click_dt = min(e_1st_click_dt,new_date);
end;
else
_ERROR_ = 0; /*No need for IORC errors*/
run;
This particular piece of code is throwing an error saying:
ERROR: The ORACLE table SUMMARY has been opened for OUTPUT. This table already exists, or there is a name conflict
with an existing object. This table will not be replaced. This engine does not support the REPLACE option.
What is the work around for the same? This question is related to a question I raised earlier (Summerizing a table in SAS)
Just change the table name from summary to something else and try..am not sure whether we can use summary as a table name since proc summary is there...not sure but try and see
As error-message says, you can't replace oracle table in DATA-step. The workaround of it would be:
1) To do all data manipulations in an interim SAS-dataset;
2) Delete all rows in an original Oracle table using PROC SQL ... DELETE ...;
3) Add new data (interim dataset) to empty Oracle table using PROC APPEND.
data temp;
set click_summ(where=(^missing(e_1st_click_dt)));
keep card_number package_sk e_1st_click_dt;
run;
data summary(drop=new_date) ;
modify summary temp(rename=(e_1st_click_dt= new_date) in=a);
by card_number, package_sk;
if a then do;
e_1st_click_dt = min(e_1st_click_dt,new_date);
end;
else
_ERROR_ = 0; /*No need for IORC errors*/
run;
Modify was the key. This will work fine with Oracle tables as well. And pretty fast too.