I am working is SAS guide 7.1 and I need to run a process with proc sql but don't work well, though it work well with step data.
The folliwing code replicate the issue
data test;
input date;
datalines;
20140101
;
run;
data test2;
set test;
date1 = input(compress(date),yymmdd10.);
format date1 date9.;
run;
The output
Code with proc sql:
proc sql;
create table test3 as select
*,
input(compress(date),yymmdd10.) format date9. as date1
from test;
quit;
The error message:
Function COMPRESS requires a character expression as argument 1.
Why COMPRESS operates in a different way with both step data and proc sql?
The compress() function is operating the same way.
But PROC SQL does not do automatic type conversion the way that a data step will. Look at the notes from your data step.
207 data test2;
208 set test;
209 date1 = input(compress(date),yymmdd10.);
210 format date1 date9.;
211 run;
NOTE: Numeric values have been converted to character values at the places given by:
(Line):(Column).
209:24
Just tell SAS explicitly that you want to convert the number 20,140,101 to the string '20140101' and then convert that string into a date value.
input(put(date,z8.),yymmdd8.)
Related
I want to convert the Db2 timestamp into SAS numeric
proc sql;
connect to db2 ;
create table db2ts as
select * from connection to db2
(select char(current timestamp)
from sysibm.sysdummy1)
as db2ts(timestm);
%put &sqlxmsg ;
%put &sqlxrc ;
disconnect from db2;
quit;
data _NULL_;
set DB2TS;
putlog 'timestmb--' timestm;
datets =input(timestm,yymmdd10.);
timets =input(substr(timestm,12),time15.);
dt2=dhms(datets,0,0,timets);
format datets date9. timets time15.6 dt2 datetime26.6;
putlog 'currdatets:' dt2;
call symput('currdatets',catx('-',put(datepart(dt2),yymmdd10.),
translate(put(dt2,tod15.6),'.',':')));
putlog 'currdatets:' currdatets;
run;
timestmb--2022-05-18-16.44.54.587001
currdatets:18MAY2022:16:44:54.587001
%put currdatets: &currdatets;
currdatets: 2022-05-18-16.44.54.587001
Proc sql:
Insert into table1
(Time, Type)
Values
(%sysfunc(quote(&currdatets)), 'A')
Error:
ERROR: Value 1 of VALUES clause 1 does not match the data type of
the corresponding column in the object-item list(in the SELECT clause).
how can I use the macro variable currdatets to insert into the DB2 table?
So your first query is not valid SQL syntax so I am not sure how it even works. Try something like:
create table db2ts as
select * from connection to db2
(select char(current timestamp) as timestmp
from sysibm.sysdummy1)
;
This will create a dataset name db2ts with a character variable named timestmp;
Which should be the similar to what you would get with this data step.
data db2ts ;
timestmp ='2022-05-17-12.02.43.387486';
run;
Now you can convert the string into a DATETIME value by first converting it into a DATE and a TIME value and then combining them.
data want ;
set db2ts;
date=input(timestmp,yymmdd10.);
time=input(substr(timestmp,12),time15.);
datetime=dhms(date,0,0,time);
format date date9. time time15.6 datetime datetime26.6;
put (_all_) (=/);
run;
Results:
timestmp=2022-05-17-12.02.43.387486
date=17MAY2022
time=12:02:43.387486
datetime=17MAY2022:12:02:43.387486
It would be easier if you could figured out if DB2 has a function, or option for the CAST() function, that can let you specify how the string is generated so that it is something that SAS can recognize immediately as a datetime.
I have a SAS field where the datatype is number and format is date9.
It has a value like 30SEP2018.
How do I convert it to a SAS date so I can do date operations?
SAS dates are stored as number starting from 1/1/1960 and it starts form number = 0 and increases by 1 for every day. Your date is stored as number and then you get from proc contents and format is to display in the way you want.
data have;
input date:date9.;
format date date9.;
datalines;
30SEP2018
;
proc contents data=have;
run;
you can calculations on above date and gives you appropriate results as shown below
data want;
set have;
new_date= date+1;
new_date1= date-1;
format new_date new_date1 date9.;
run;
proc print; run;
I have a table in SAS where in one column, the date is stored (e.g. "2005/10").
How do I have to convert this to a SAS data format?
Among many other tries, I tried this code:
data test;
format date YYMMS.;
date = input(ObservationMonth, YYMMS.);
put date=date9.;
run;
You could just use the anydtdte. informat.
data want;
format date yymms.;
text="2005/10";
date=input(text,anydtdte.);
put date;
run;
This informat detects most date formattings and converts the character-stored value to a SAS date.
One way is to use substr() and mdy() to extract the date components:
data _null_;
ObservationMonth ="2005/10";
date =mdy(substr(ObservationMonth,6,2),1,substr(ObservationMonth,1,4));
put date = date9.;
run;
Another option is to use the anydtdte informat (note that results may differ depending on your locale):
data _null_;
ObservationMonth ="2005/10";
date =input(ObservationMonth,anydtdte.);
put date = date9.;
run;
Yet another option is to modify the input to enable use of the YYMMDDw. informat:
data _null_;
ObservationMonth ="2005/10";
date =input(ObservationMonth!!'/01', YYMMDD10.);
put date = date9.;
run;
you're fantastic, guys! Thank you so much, with a "set" statement it works fine!
How can I print (and export to file) monthly and weekly average of value? The data is stored in a library and the form is following:
Obs. Date Value
1 08FEB2016:00:00:00 29.00
2 05FEB2016:00:00:00 29.30
3 04FEB2016:00:00:00 29.93
4 03FEB2016:00:00:00 28.65
5 02FEB2016:00:00:00 28.40
(...)
3078 08MAR2004:00:00:00 32.59
3079 05MAR2004:00:00:00 32.75
3080 04MAR2004:00:00:00 32.05
3081 03MAR2004:00:00:00 31.82
EDIT: I somehow managed to get the monthly data but I'm returning average for each month separately. I would to have it done as one result, namely Month-Average+export it to a file or a data set. And still I have no idea how to deal with weeks.
%macro printAvgM(start,end);
proc summary data=sur1.dane(where=(Date>=&start
and Date<=&end)) nway;
var Value;
output out=want (drop=_:) mean=;
proc print;
run;
%mend printAvgM;
%printAvgM('01jan2003'd,'31jan2003'd);
EDIT2: Here is my code, step by step:
libname sur 'C:\myPath';
run;
proc import datafile="C:\myPath\myData.csv"
out=SUR.DANE
dbms=csv replace;
getnames=yes;
run;
proc sort data=sur.dane out=sur.dane;
by Date;
run;
libname sur1 "C:\myPath\myDB.accdb";
run;
proc datasets;
copy in=sur out=sur1;
select dane;
run;
data sur1.dane2;
set sur1.dane;
date2=datepart(Date);
format date2 WEEKV11.;
run;
The last step results in NOTE: SAS variable labels, formats, and lengths are not written to DBMS tables. and the format of dane2 variable is DATETIME19..
Ok, it's small enough to handle easily then. I would recommend first converting your datetime variable to a date variable using DATEPART() function and then use a format within PROC MEANS. You can look up the WEEKU and WEEKV formats to see if they meet your needs. The code below should be enough to get you started. You could do the monthly without the date conversion, but I couldn't find a weekly format for the datetime variable.
*Fake data generated;
data fd;
start=datetime();
do i=1 to 3000000 by 120;
datetime=start+(i-1)*30;
var=rand('normal', 25, 5);
output;
end;
keep datetime var;
format datetime datetime21.;
run;
*Get date variable;
data fd_date;
set fd;
date_var = datepart(datetime);
date_month = put(date_var, yymon7,);
Date_week = put(date_var, weekv11.);
run;
*Monthly summary;
proc means data=fd_date noprint nway;
class date_var;
var var;
output out=want_monthly mean(var)=avg_var std(var)=std_var;
format date_var monyy7.;
run;
*Weekly summary;
proc means data=fd_date noprint nway;
class date_var;
var var;
output out=want_weekly mean(var)=avg_var std(var)=std_var;
format date_var weekv11.;
run;
Replace date_var with the new monthly and weekly variables. Because these are character variables they won't sort properly.
I am trying to create a SAS informat for the following date format:
"yyyy-mm-dd hh:ii:ss.SSS UTC", example: "2016-01-14 10:31:01.456 UTC"
I've gotten close using the following format code:
PROC FORMAT;
PICTURE MyDate other='%0Y-%0m-%0d %0H:%0M:%0s UTC' (datatype=datetime);
RUN;
Unfortunately when I try and use this as an INFORMAT I get an error "can't find format MyDate", as it hasn't been defined as an informat, just an output format.
I can try and create an informat from a dataset created from this format, but due to the milliseconds constraint it will only create values that map to times with .000 in the milliseconds section. For example:
DATA MyInDate ;
RETAIN FMTNAME "MyInputDate" type "I" ;
do label = "1jan2016:00:00:00"dt to
"2feb2016:00:00:00"dt by 1;
start = trim(left(put(label,MyDate.)));
output ;
end ;
RUN;
PROC FORMAT CNTLIN=MyInDate;
RUN;
Even if I were able to enumerate a dataset with milliseconds it would be prohibitively large. Since my dates can span years.
Is it possible to truncate my input data BEFORE passing it to the informat? I don't care about the milliseconds or the UTC qualifier. I can't change the input data.
EDIT: Using anydtdtm. as an informat results in empty values without error messages. Here is the data step making use of this informat:
DATA WORK.ImportDatTest;
LENGTH
'Event Time'n 8
;
FORMAT
'Event Time'n DATETIME25.
;
INFORMAT
'Event Time'n anydtdtm.
;
INFILE DATALINES DLM=','
;
INPUT
'Event Time'n : ANYDTDTM.
;
DATALINES;
2016-01-11 17:23:34.834 UTC
2016-01-11 17:23:34.834 UTC
2016-01-11 17:23:34.834 UTC
;
RUN;
Unfortunately, there is no way to create a picture informat in SAS currently. You would need to convert your data to a format SAS has a built-in informat for, or use a function or similar to format the data.
However, yours already is in such a format, so you shouldn't need to create an informat.
data test;
x="2015-10-05 10:12:24.333 UTC";
y=input(x,anydtdtm.);
put y= datetime17.;
run;
You can certainly truncate data while using an informat; by specifying a length in the informat, it will truncate to that length.
Here's an example using input from datalines:
data test;
infile datalines dlm=',' dsd;
input y :anydtdtm32.;
put y= datetime22.3;
datalines;
2015-10-05 10:12:24.333 UTC
2014-03-01 08:08:05.435 UTC
2013-01-01 23:02:05.445 UTC
;;;
run;