SAS delete table if 0 Observastions - sas

Is there a procedure that will check to see if a table has 0 observations, and if so then delete it? I assumed there could be an easier way besides manually checking and deleting each table. I'm using a loop command and most of the tables I generate with it will have data but several will have 0 observations.
Thanks if anyone can help.

Assuming you don't have any reason not to trust the metadata, you could look at dictionary.tables:
proc sql;
select memname from dictionary.tables
where libname='WORK' and nobs=0;
quit;
So for example you could pull that into a macro variable and delete the tables in a PROC SQL or PROC DATASETS statement.
proc sql;
select memname into :dellist separated by ' ' from dictionary.tables
where libname='WORK' and nobs=0;
quit;
proc datasets nolist;
delete &dellist;
quit;

Related

sas: how to create a variable containing a list of different variables in 2 datasets

I'm kinda new to SAS.
I have 2 datasets: set1 and set2.
I'd like to get a list of variables that's in set2 but not in set1.
I know I can easily see them by doing proc compare and then listvar,
however, i wish to copy&paste the whole list of different variables instead of copying one by one from the report generated.
i want either a macro variable containing a list of all different variables separated by space, or printing out all variables in plain texts that I can easily copy everything.
proc contents data=set1 out=cols1;
proc contents data=set2 out=cols2;
data common;
merge cols1 (in=a) cols2 (in=b);
by name;
if not a and b;
keep name;
run;
proc sql;
select name into :commoncols separated by ','
from work.common;
quit;
Get the list of variable names and then compare the lists.
Conceptually the simplest way see what is in a dataset is to use proc contents.
proc contents data=set1 noprint out=content1 ; run;
proc contents data=set2 noprint out=content2 ; run;
Now you just need to find the names that are in one and not the other.
An easy way is with PROC SQL set operations.
proc sql ;
create table in1_not_in2 as
select name from content1
where upcase(name) not in (select upcase(name) from content2)
;
create table in2_not_in1 as
select name from content2
where upcase(name) not in (select upcase(name) from content1)
;
quit;
You could also push the lists into macro variables instead of datasets.
proc sql noprint ;
select name from content1
into :in1_not_in2 separated by ' '
where upcase(name) not in (select upcase(name) from content2)
;
select name from content2
into :in2_not_in1 separated by ' '
where upcase(name) not in (select upcase(name) from content1)
;
quit;
Then you could use the macro variables to generate other code.
data both;
set set1(drop=&in1_not_in2) set2(drop=&in2_not_in1) ;
run;

Using Proc sql to get statiscs for many variables

I want to use Porc sql to create a data set that contains some statistics as min and max for a lots of variables. The code below only returns a data set with min and max for first variable, for the rest of variables min and max are not show in the data set.
proc sql;
CREATE TABLE Lib.VarNum AS
%do i=1 %to &nvars;
select min(%SCAN(&numvar,&i)) as Min%SCAN(&numvar,&i),
max(%SCAN(&numvar,&i)) as Max%SCAN(&numvar,&i)
from &data (keep= _numeric_);
%end;
quit;
Somebody can help me?
using proc means is best way to do this.
proc means data=sashelp.cars noprint;
var _numeric_;
output out=want (drop= _type_ _freq_ )min(_numeric_) =
max(_numeric_) =/autoname;
run;
but if you want to so it by Proc SQL easiest to macrovariables from dictionary.columns and use them in your tables.
/* creating macrovariables using dictionary.columns*/
proc sql noprint;
select 'min('|| trim(name)||') as min_'||name,
'max('|| trim(name)||') as max_'||name
into :min separated by ',' , :max separated by ','
from dictionary.columns
where libname ='SASHELP'
and memname ='CARS'
and upcase(type) ='NUM';
Values of macrovariable can be checkedly and only partially shown
%put &min;
min(MSRP) as min_MSRP,min(Invoice) as min_Invoice,min(EngineSize) as min_EngineSize
use this macro variables in proc sql statement as shown below.
proc sql;
create table want as
select &min, &max from sashelp.cars;

Insert and update using proc sql simultaneously in SAS

I am importing a file using proc import
proc import datafile="/opt/Export_d.csv" replace
out=work.export_data; run;
THEN I SELECTED 2 VARIABLES FROM EXPORTED TABLE HAVING SOME CONDITION
proc SQL;
create table work.login2
as select ' SURVEY_ID'n, TIME format=datetime20.,' USERNAME'n
from work.export_data
having TIME=max(TIME) and ' USERNAME'="sasdemo";
quit;
then i created a macro for survey_id because i have to update a value with the Survey_id reference in different table shown in below code:
proc SQL;
select max(' SURVEY_ID'n) into: sid from work.login2;
quit;
now if the ID is blank then i don't have to insert anything but if we have survey_id we have update few columns in a table using below code which is not happening.
proc SQL;
case when ' SURVEY_ID'n is not null then update table_name set SAS_TRACKING_CODE="&Trackingcode."
where SURVEY_ID=&sid.
else end;
quit;
The syntax in your proc sql is not valid. At all. case whencan only be used within statemements like select, where, order by.
The following will do your update if SURVEY_ID is not blank:
proc sql;
update table_name
set SAS_TRACKING_CODE="&Trackingcode"
where SURVEY_ID=&sid. and SURVEY_ID is not null
;
quit;
If what you want is to execute the update only when a condition is true, you should use a macro.
EDIT: that macro would look like this:
%macro update;
%if %symexist(sid) and not &sid = %then %do;
proc sql;
update table_name
set SAS_TRACKING_CODE="&Trackingcode"
where SURVEY_ID=&sid.
;
quit;
%end;
%mend;

SAS EG : Selecting the most recent dataset from a library

I use sas EG V5.1. I need to select the most recent dataset saved within a permanent library. How can I do that without having to look at the library?
employee_2016_09_04
employee_2016_09_15
first_2016_09_04
first_2016_09_14
I need to select the most recent tables of either category and these are SAS datasets. I currently have a macro variable defined for the date which I update manually each time I run a code. Any help is appreciated. Thanks
You can use dictionary tables.
Using modification (modate) or creation column (crdate).
proc sql;
create table tables as
select memname, modate
from dictionary.tables
where libname = 'SASHELP'
order by modate desc;
quit;
Or use sort on variable name (memname).
proc sql;
create table tables as
select memname
from dictionary.tables
where libname = 'SASHELP'
order by memname desc;
quit;
Or the same thing using sashelp views
data tables;
set sashelp.vtable;
where libname = 'SASHELP';
keep memname modate;
run;
proc sort data=tables;
by descending modate;
run;

How do you read multiple specific datasets and append to one big dataset?

How do you read multiple specific datasets and append to one big dataset?
For example I within a library I have 100s of datasets but I only want to append the datasets that have _du1, _du2
The format and column names are the same
My stab of it doesnt work:
PROC SQL NOPRINT;
SELECT memname INTO :tab1-:tab103 FROM sashelp.vtable
where memname like '_DU%';
SELECT count(*) INTO :obs FROM sashelp.vtable
where memname like '_DU%';
QUIT;
%macro rubber;
%do i=1 %to i=&obs;
proc append base=tot_comb data=&&tab&i force;
run;
%end;
%mend;
%rubber;
PROC APPEND may not actually be faster in this case, or at least not faster by enough to justify doing it, than just writing a datastep.
data tot_comb;
set work._DU:; *or your libname;
run;
This will work if you are on SAS 9.2 or later. If you're on 9.1 or earlier, you'll need to do one proc sql step, like
proc sql;
select memname into :namelist separated by ' '
from dictionary.columns
where libname='WORK' /* or your libname */
and memname eqt '_DU';
quit;
*eqt is like starts with;
data tot_comb;
set &namelist;
run;
That only requires one pass to write, and I'm not sure it will be much slower than so many calls to PROC APPEND.
Here is some code that will get you all the data set names from a given library with some characteristics (starts with _DU). You could use the final macro in a variety of ways to append data sets.
Data _DU1;
var="One";
Run;
Data _DU2;
var="Two";
Run;
PROC SQL;
create table main as
SELECT *
FROM DICTIONARY.COLUMNS
WHERE UPCASE(LIBNAME)="WORK" AND
UPCASE(MEMNAME) like '_DU%';
Select memname
into :dsn separated by ' '
from main;
QUIT;
%Put &dsn;
EDIT (according to your comment)
I added some UPCASE statements and used your count macro var for the number of tab macros
Narrowing your where statement should make your code more efficient
Try this (some of the code is untested):
PROC SQL NOPRINT;
SELECT count(*)
INTO :obs
FROM sashelp.vtable
where UPCASE(LIBNAME)="<YOUR LIB IN UPCASE>" AND
upcase(memname) like '_DU%';
%Let obs=&obs;
SELECT memname
INTO :tab1-:tab&obs
FROM sashelp.vtable
where UPCASE(LIBNAME)="<YOUR LIB IN UPCASE>" AND
upcase(memname) like '_DU%';
QUIT;
%macro rubber;
%do i=1 %to &obs;
proc append base=tot_comb data=&&tab&i force; run;
%end;
%mend;
%rubber;