I'm Converting some Proc Sql statements to t-sql. I have one that looks like
Proc SQL
Select
... (extra lines of code here that select normal columns)
. as NewColumnAlias,
... (more lines of code here that select normal columns)
From $syslast
END
What does the "." in the above code mean? What column does it select?
In SAS a period denotes a numeric missing value. This essentially sets your column to missing everywhere.
Related
I have two datasets. The first, big_dataset, has around 3000 columns, most of which are never used. The second, column_list, contains a single column called column_name with around 100 values. Each value is the name of a column I want to keep.
I want to filter big_dataset so that only columns in column_list are kept, and the rest are discarded.
If I were using Pandas dataframes in Python, this would be a trivial task:
cols = column_list['column_name'].tolist()
smaller_dataset = big_dataset[cols]
However, I can't figure out the SAS equivalent. Proc Transpose doesn't let me turn the rows into headers. I can't figure out a statement in the data step that would let this work, and as far as I'm aware this isn't something that Proc SQL could handle. I've read through the docs on Proc Datasets and that doesn't seem to have what I need either.
To obtain a list of columns from column_list to use against big_dataset, you can query the column_list table and put the result into a macro variable. This can be achieved with PROC SQL and the SEPARATED BY clause:
proc sql noprint;
select column_name
into :cols separated by ','
from column_list;
create table SMALLER_DATASET AS
select &cols.
from WORK.BIG_DATASET;
quit;
Alternatively you may use SEPARATED BY ' ' and then use the resulting list in a KEEP statement or dataset option:
proc sql noprint;
select column_name
into :cols separated by ' '
from column_list;
quit;
data small_dataset;
set big_dataset (keep=&cols.);
/* or keep=&cols.; */
run;
I have a tables which have columns from col1 to col10.
I would like to append a string such as italy_col1 to italy_col10.
how can I achieve this without a macro.
Since i am joining multiple table i want to append a text "Italy" for all column in table 1 and "USA" in table 2. I tried below example it doesnt suit my requirement
https://support.sas.com/kb/48/674.html
cats function appends all the values in the column of the tables. Any suggestions?
One way is to generate macro variables and then use those in your code.
First get lists of variables to rename from TABLE1 and TABLE2.
proc sql noprint;
select catx('=',name,cats('Italy_',name) into :rename1 separated by ' '
from dictionary.columns
where libname="WORK" and memname="TABLE1" and upcase(name) ne 'ID'
;
select catx('=',name,cats('USA_',name) into :rename2 separated by ' '
from dictionary.columns
where libname="WORK" and memname="TABLE2" and upcase(name) ne 'ID'
;
quit;
Then use the list of rename pairs in your code that merges the datasets.
data want;
merge table1(rename=(&rename1)) table2(rename=(&rename2));
by id;
run;
Note this will only work when the number of variables to rename is small enough to fit into a single macro variable. If the list is longer just use another method, such as a data step, to generate the same code.
Also watch out for variable names that are too long. SAS has a limit of 32 bytes for variable names so adding 4 or 7 extra characters might result in names that are too long. You might just truncate to 32 characters , but then you risk forming duplicate names.
I need to have a special character (% and space) in the alsias name of a proc sql statement.
proc sql DQUOTE=ANSI;
create table final_data as
select a.column1 as XYZ,
((a.colum2/b.colum2)-1) as "% VS LY"
from table1 a
join table2 b on a.colum3=b.colum3;
quit;
according to the documention, having the option proc sql DQUOTE=ANSI should work..
http://support.sas.com/documentation/cdl/en/acreldb/63647/HTML/default/viewer.htm#a001393333.htm
However, I'm getting this error in SAS 9.3
ERROR: The value % VS LY is not a valid SAS name.
What should I do to make this work?
Thank you so much in advance!
Perhaps a simpler solution would be to use standard naming and a SAS label. If the computed value is between 0 and 1 you can also add a SAS format.
((a.colum2/b.colum2)-1) as vs_ly_pct label='% VS LY' format=percent5.2
If you truly want non-standard column names, you will also need to set
options validvarname = any;
before the Proc SQL.
In SQL an alias is what you use to prefix variable references to tell which input table (or subquery) the variable comes from. Like the a and b in your query. What you are talking about is the variable NAME.
SAS variable names normally are restricted to underscore and alphanumeric characters (and cannot start with a number), but variable LABELS can be any string. You can just specify the label after the name.
select a.column1 as XYZ
, ((a.colum2/b.colum2)-1) as var2 '% VS LY'
Or use the SAS specific LABEL= syntax
select a.column1 as XYZ
, ((a.colum2/b.colum2)-1) as var2 label='% VS LY'
How do i write in sas:
proc sql;
create table THIS as
select *
from MAIN(keep=id col1 -- col34)
where (AT LEAST ONE OF THE COLUMNS contains 1) ;
;
I am having a problem figuring out how to write that last line bc I want to keep all columns so I am not just checking one column i want to check for all of them.
You will have more flexibility if you use a DATA step instead of PROC SQL since you cannot use variable lists in PROC SQL code.
Assuming all of the variables in your list are numeric you could do something like this.
data this;
set main ;
keep id col1 -- col34;
if whichn(1,of col1 -- col34);
run;
Tom is right, the best approach is with a data step. If you are certain you want to do it with SQL though you could do something like this:
proc sql noprint;
create table THIS as
select *
from MAIN(keep=id col1 -- col34)
where sum(col1,col2,col3, ... ,col34)
;
quit;
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.*