I have a sas data set which has date field which is in the format "04JAN2012" and using format, I am converting it to "2012-01-04" in a separate data step.
The problem arises when I am using a simple where statement in proc SQL which is using a 'where' condition like---- select * from temp where temp.active_date > '2012-01-01'
The error message at this point is "Expression using equals (>) has components that are of different data types."
Please help !
The best way would be to convert your string ('2012-01-01') into a SAS date before doing the filter, eg via macro:
%let date_filter='2012-01-01';
%let mydate=%sysfunc(mdy(
%substr(&date_filter,7,2)
,%substr(&date_filter,10,2)
,%substr(&date_filter,2,4)));
proc sql;
select * from temp where temp.active_date > &mydate;
If you're using FORMAT and not PUT (which converts to character internally), you aren't actually changing anything about the date beyond how it is displayed (and used in some grouping functions). Internally, active_date still is a numeric SAS date.
As such, you simply need to use the correct format of date constant. While you are using PROC SQL, you still are in SAS, which formats date constants differently than SQL Server or Oracle.
'01JAN2012'd is the correct format of date constant for that, so your code should be:
select * from temp where temp.active_date > '01JAN2012'd;
If you are generating this comparison value in some fashion (not writing it into code), you can generate it properly by PUTting (or FORMATting) the value being generated to DATE9. format.
Related
Good afternoon
so I have BEST12.
I want to convert to date9.
so my code is
data step7_1;
set step7;
service_day2= input(put(datedate, z8.),yymmdd8.);
format service_day2 date9.;
run;
the error is
NOTE: Invalid argument to function INPUT at line 92 column 15.
NOTE: Mathematical operations could not be performed at the following places. The results of the
operations have been set to missing values.
Each place is given by: (Number of times) at (Line):(Column).
4 at 97:15
how can I fix this issue?
Thanks
Kazu
A format is just a mechanism of displaying data, so there's no need to apply functions to 'convert' it, just apply a format using the format statement:
data step7_1;
set step7;
service_day2 = datedate;
format service_day2 date9.;
run;
If you don't need a new variable, you can just use the format statement alone:
data step7_1;
set step7;
format datedate date9.;
run;
Or you can just alter the original dataset directly using PROC DATASETS:
proc datasets lib=work nolist;
modify step7;
format datedate date9.;
quit;
This has the advantage of not copying data, it will run more quickly and simply modifies the dataset metadata in place.
Can I pass format for the time or date datatype in SQL Server 2008 R2?
Example: a column with time format like hh:mm ONLY
I searched and found that I can pass fractional second scale with like below but that is will get met a time format with seconds hh:mm:ss and I only want hh:mm
Note
I do not want to avoid this case in the select statement it wont help me in when using the column in Crystal Reports and I am not able to format it in Crystal Reports there is no date-time tab in format object option
_HOUR time(0);
I do not want to avoid this case in the select statement ...
I am not able to format it in crystal report
But you do need a select statement to produce a report, so one way is to use a "style number" (8) with the convert() function - but you only want the leading 5 characters, so use char(5) for the result. i.e.
select convert(char(5), [datetime_or_time_column] ,8) as "hh:mm"
from thetables
You do not indicate at all how you gather the data for the report, but if using a temp table or stored procedure (or even a view) you can use the convert syntax above when producing the result. Note is is possible to use T-SQL's format() like so format(getdate(),'HH:mm') but this is usually slower than using convert().
If you have permission to add calculated columns to your table AND this wanted hh:mm data is deterministic, you could also use the convert syntax shown above for a calculated column.
I am trying to see if a variable falls into a boundary of dates.
I hate a DATE1 already in MMDDYY10.
I use the following code
DATA GIANT;
SET GIANT;
UPPER_BOUND= intnx('week', DATE1, 2);
run;
it gives me back something in Num 8.
I want to restore it to MMDDYY10. so that I can compare it to my other dates.
Two Questions:
How can I convert a NUMERIC of length 8 into a date?
Why does intnx ... designed to work with dates return a numeric and not something in the same format?
I tried to convert it like this:
DATA GIANT;
SET GIANT;
UP_DATE=INPUT(PUT(UPPER_BOUND, 8.), MMDDYY10.);
FORMAT UP_DOS MMDDYY10.;
run;
but now it all comes up as null.
SAS Dates are always numeric (# of days since 1/1/1960). Date formats are simply a way of making that numeric readable. INTNX returns a numeric because that's all a date is; it's up to you to apply a date format to the new variable.
In your case it's very simple. You almost got it right in your attempt, but you don't need the input/put business.
data giant;
set giant;
upper_bound=intnx('week',Date1,2);
format upper_bound MMDDYY10.;
run;
INPUT converts human readable text into a value (usually a number). PUT converts a value into human readable text. PUT(INPUT(...)) is commonly used to convert a formatted value into a different kind of formatted value (for example, to convert the string "1/1/1960" to "01JAN1960"); INPUT(PUT(...)) is not very commonly used unless you are parsing the string that PUT created (such as, to read just a particular date element or something like that). Both change the type (from numeric to character in PUT or other way in INPUT) in most cases and certainly change the actual stored value.
Applying a format to a numeric column leaves the column as a numeric (which is usually good) but tells SAS how to display that numeric so you can understand it (also usually good). So underneath the value is 19857 but what is displayed is 05/14/2014.
I have imported some data into SAS from some Excel spreadsheets sent to me. When I view the output from the imported table, the date appears as "01APR2014" and maintains chronological order. When I view the column properties the type is "Date" and the length is 8. Both the format and informat are DATE9.
I need to be able to convert this date to week-year and month-year, but no matter what I try I always get Jan, 1960.
Using proc sql, I used the below to get the week-year,
"(put(datepart(a.fnlz_date),weeku3.))|| "-" ||(put(datepart(a.fnlz_date),year.)) as FNLZD_WK_YR,"
but all I got was "W00-1960". I've used the formula above successfully many times before with SAS datetime values.
For month-yr, using proc sql, I tried
"datepart(a.fnlz_date) as DT_FNLZD format=monyy.,"
but the only value returned is "JAN60".
I also tried using SUBSTR, but got an error saying it requires a character argument, so SAS must see it as a number at least.
My question; does anyone know a way to get the week-yr and/or month-yr from this format? If so, how? I'm not opposed to using a data step, but I haven't been able to get that to work either.
Thanks in advance for any help or insight provided.
datepart converts datetimes to dates. Not helpful here.
If you're just displaying this, then you have a few options, particularly for month. You can just change the format of the variable (This changes what's displayed, but not the underlying value; consider this a value label).
When you use this like this (again, it looks like you got most of the way there):
proc sql;
select datevar format=monyy5. from table;
quit;
Just don't include that datepart function call as that's not appropriate unless you have a datetime. (Date=# of days since 1/1/1960, Datetime = # of seconds since 1/1/1960:00:00:00).
That will display it with MONYY5. format, which would be MAY10 for May, 2010. You have some other format options, see the documentation on formats by category for more details.
I can't think of a Week format that matches what you want (there are week formats, like WEEKW., as you clearly found, but I don't know that they do exactly what you want. So, if you want to build one yourself, you can either build a custom picture format, or you can make a string.
Building a custom picture format isn't too hard; see the documentation on Picture formats or google SAS Date Picture Format.
proc format;
picture weekyear (default=8)
low-high = 'W%0U-%Y' (datatype=date) ;
quit;
Now you can use that as a normal format.
To get at the week/etc. to build values, you can also use functions week(), month(), etc., if that's easier.
Since the data was already in a date format, I only needed to drop the DATEPART function that only works with datetime values. So, for month-yr,
"a.fnlz_date as fnlz_mnth format=monyy.,"
gives me the results I'm looking for.
Cheers!
I'm fairly new to SAS and recently we migrated some of our SAS datasets to a SQL Server table but we are still using SAS to do our analysis. I have run into a problem when SAS is trying to bring in the data from the SQL Server table and have SAS check if the srv_edt date is between the SAS dates of dos_beg_dt1 and dos_end_dt1.
When SAS tries to compare the dates I get an error of: ERROR: WHERE clause operator requires compatible variables.
The dos_beg_dt1, dos_end_dt1, and srv_edt (SQL date format) all "appear" in the format of yyyy-mm-dd. When I bring the srv_edt into a SAS table it reads it as a character date. So I've tried changing the format of the dates and then I will get an error like:ERROR: Variable srv_edt has been defined as both character and numeric. I can't seem to find the correct format or function to get SAS to do the comparison to see if the srv_edt (SQL) is between the dos_beg_dt1 and dos_end_dt1 SAS dates.
The code I use is as follows:
libname sql odbc dsn=test schema=dbo;
%let dos_beg_dt1 = %sysfunc(intnx(qtr,&date,-1,beginning),yymmdd10.);
%let dos_end_dt1 = %sysfunc(intnx(qtr,&date,-1,end),yymmdd10.);
data sample;
set sql.table;
where &dos_beg_dt1 <= srv_edt <= &dos_end_dt1;
run;
For reference I am using SAS 9.2 to connect via odbc to SQL Server 2008.
Any help or advice would be greatly appreciated.
SAS stores and uses dats as numeric variables. If you had not identified the column srv_edt as a date column when you migrated the database to SQL server everything would now process correctly.
I assume that currently and into the future you will just store the tables in SQL server and all the processing will be in SAS.
You have a few options.
1/ re-migrate the SAS tables but identify all the date, time and datetime columns as just numeric. They all can be stored as 8 byte floating point. The date variables may also be stored (in SQL Server) is long integers. The code would need a slight change so that the macro variables would be numeric.
%let dos_beg_dt1 = %sysfunc(intnx(qtr,&date,-1,beginning));
%let dos_end_dt1 = %sysfunc(intnx(qtr,&date,-1,end));
2/ keep the date, time, and datetime variables in SQL Server format and change the data type of the column when using the data. (Note the reverse will be necessary on output). SQL Server will present the date variables as strings (character) so that your expression above will need to be -
%let dos_beg_dt1 = %sysfunc(intnx(qtr,&date,-1,beginning));
%let dos_end_dt1 = %sysfunc(intnx(qtr,&date,-1,end));
data sample;
set sql.table;
where &dos_beg_dt1 <= (input(srv_edt, yymmdd10.0)) <= &dos_end_dt1;
That to make sure when using SAS processing the type is numeric which is what the input function will do.
3/ keep the date, time, and datetime variables in SQL Server format and change your working to accommodate that fact. That is comparisions will be using character data and output will need to produce characters. SQL Server will present the date variables as strings (character) so that your expression above will need to be -
%let dos_beg_dt1 = %sysfunc(intnx(qtr,&date,-1,beginning), yymmdd10.);
%let dos_end_dt1 = %sysfunc(intnx(qtr,&date,-1,end), yymmdd10.);
data sample;
set sql.table;
where ("&dos_beg_dt1" <= srv_edt) and
(srv_edt <= "&dos_end_dt1");`
Note double quotes " " required surrounding macro variables as this
comparison is numeric.
If the column srv_edt is showing up in your SAS data set as a character variable, that means it is really a character variable or it's been converted to character by the ODBC driver you are using (possibly because the native data type is not supported by ODBC).
You'd be better off changing this to a PROC SQL pass-thru query if possible. You would need to figure out the native syntax that corresponds to the SAS intnx function (and I cannot help you there). As written, the entire table must be read (because you are using a SAS function). If you use a pass-thru query, SAS will only receive the rows that match the whee clause.
There might be setting in the ODBC driver that control this behavior. I'll add the ODBC and SQL Server tags to your question; you may get more "hits".
SQL Server introduced new date and datetime types in SQL Server 2008 (prior, there was only one type for all date/datetime variables). This usage note suggests that you need to install a new set of SQL Server ODBC drivers for SAS to read the date variables correctly. It suggests this would be installed normally if you have SQL Server 2008 Tools (like SQL Server Management Studio) on the machine that is doing the ODBC connection, but you might have multiple drivers installed and need to ensure you are using the right one.
That said, it is not a bad idea to use pass-through SQL to pull the data across, as that might make it easier to do the pull (as you don't have to worry as much about the ODBC driver). The generalized pass through connection string is
proc sql;
connect to odbc (required="driver=sql server native client 10.0;
Server=server;Trusted_Connection=Yes;DATABASE=database;");
create table X as select * from connection to odbc(... sql server native code here ...);
quit;
From your question it sounds like you're more of a SQL person and can then construct the query yourself; if you are not, either edit the question to include that request (and then either a SQL Server person or myself will answer). You can use SAS macro variables in that query (ie, to pass the current date) as long as you do not enclose them or the query in single quotes.