I would like to make a new dummy variable equals 1, if OBSdate is between Startdate and ENDdate.
However, OBSdate is til Date9. format and END- and Startdate is in format Datetime.25.6.
I tried the following code:
proc sql;
create table test2 as
select *,
case when OBSdate between Startdate and Enddate then 1 else 0 end as dummy
from work.test1
;
quit;
Can anyone help me?
If i try to change format for the Enddate variable to format Date9. if only shows ******.
Thanks in advance.
Related
This is actually something I want to type into query builder in SAS EG. I am trying to filter down a data set that has dates like this:
SEP2021
AUG2021
JUL2021
etc…
I’m trying to use query builder to filter it with a WHERE statement. I want the table to have only the results dated for last month. So running it now should give SEP2021, and running it next month would give OCT2021, etc…
How can I do this with a WHERE statement?
Use intnx(). Assuming that all the dates start on the first of the month:
where date = intnx('month', today(), -1, 'B');
If they don't:
where intnx('month', date, 0, 'B') = intnx('month', today(), -1, 'B');
You can use the INTCK function to compute the number calendaring intervals between two dates.
Example:
data have;
input datestring $; datalines;
SEP2021
AUG2021
JUL2021
run;
proc sql;
create table want as
select * from have
where intck('month',input(datestring,monyy7.),today()) = 1
;
Here is the answer from KurtBremser in SAS communities, this worked for me! I did not realize what format I had converted the character value into. PROC CONTENTS revealed my values were Numeric, format DTDATE9.
Full thread here: https://communities.sas.com/t5/SAS-Enterprise-Guide/How-can-PROC-SQL-return-only-results-from-the-previous-month/m-p/774523
Solution below:
“
So it IS a datetime value, not a date. You need to use DATEPART to extract the date from it:
data have;
input date_column datetime19.;
format date_column dtdate9.;
datalines;
01sep2021:01:02:03
01oct2021:04:05:06
;
proc contents data=have;
run;
proc sql;
select *
from have
where datepart(date_column) = intnx('month',today(),-1,'b');
quit;
Partial result:
# Variable Typ Länge Ausg.Format
1 date_column Num 8 DTDATE9.
date_column
01SEP2021
“
I have a SAS program I want to automate to run. I have to pull the first date & the last date of the month with the time stamps.
This is what it looks like hard coded - that does work! But I don't want to change it every month.
%let st_dt= '2020-10-01-00.00.00';
%let ed_dt= '2020-10-31-23.59.59';
PROC SQL;
SELECT t1.ENTRYTIME
FROM MYTABLE t1
WHERE t1.ENTRYTIME BETWEEN &st_dt. AND &ed_dt.
I have tried so many different things but cannot seem to get it to work. And BONUS, I'm pulling from transactional tables that have over 17 BILLION - yes BILLION WITH A B records. I've tried using datepart on the ENTRYTIME & casting as a date - but with that many records it just runs forever and eventually gets killed - or just flat out fails! :(
This is what I've tried so far - neither PROC SQL work.
%let start=%sysfunc(intnx(month, %sysfunc(today()),-1), date9.);
%let end=%sysfunc(intnx(month, %sysfunc(today()),-1,e), date9.);
PROC SQL;
SELECT t1.ENTRYTIME
FROM MYTABLE t1
WHERE cast(t1.ENTRYTIME as date) BETWEEN &start. AND &end.
PROC SQL;
SELECT t1.ENTRYTIME
FROM MYTABLE t1
WHERE cast(t1.ENTRYTIME as date) BETWEEN &start. AND &end.
So if you can get me a macro or a let statement or anything that is formatted like this to automatically update without human intervention: '2020-10-01-00.00.00' & '2020-10-31-23.59.59' - BRING IT ON! Thank you for your help!!
Just tack on the time suffix as constant text.
%let st_dt= "%sysfunc(intnx(month,%sysfunc(today()),-1,b),yymmddd10.)-00.00.00";
%let ed_dt= "%sysfunc(intnx(month,%sysfunc(today()),-1,e),yymmddd10.)-23.59.59";
You probably want to pass through to ensure best performance. The core syntax in the pass through is
entrytime >= 'yyyymmdd' and entrytime < 'yyyymmdd'
^^^^^^^^ ^^^^^^^^
1st of month 2nd of month
or
entrytime >= 'yyyymmdd' and entrytime < 'yyyymmdd'
^^^^^^^^ ^^^^^^^^
last of month 1st of next month
Example:
%let today = %sysfunc(date());
%let month_first_dt = %sysfunc(intnx(MONTH,&today,0));
%let month_last_dt = %sysfunc(intnx(MONTH,&today,0,E));
%let month_first = %sysfunc(intnx(DAY,&month_first_dt,0),yymmddn8.);
%let month_first_next = %sysfunc(intnx(DAY,&month_first_dt,1),yymmddn8.);
%let month_last = %sysfunc(intnx(DAY,&month_last_dt,0),yymmddn8.);
%let month_last_next = %sysfunc(intnx(DAY,&month_last_dt,1),yymmddn8.);
%let ss_MF_literal = %sysfunc(quote(&month_first,%str(%')));
%let ss_MFN_literal = %sysfunc(quote(&month_first_next,%str(%')));
%let ss_ML_literal = %sysfunc(quote(&month_last,%str(%')));
%let ss_MLN_literal = %sysfunc(quote(&month_last_next,%str(%')));
libname remote sqlsrv 'connection string';
proc sql;
create table sas_table as select * from connection to remote
(
select entrytime from remote-table-name
where
entrytime >= &ss_MF_literal and entrytime < &ss_MFN_literal
or
entrytime >= &ss_ML_literal and entrytime < &ss_MLN_literal
)
;
I am trying to get the current month records from a table. Since this is going to be an automated monthly job, I can't give explicit values in where clause. So I am using the intnx function to get the month's start and end date. Then comparing them with the table value (date) in where clause. I tried different date formats but every time I am getting the same error: "ERROR: Expression using equals (=) has components that are of different data types."
Below is my script. What am I doing wrong?
DATA _NULL_;
CALL
SYMPUT('MonthStart',TRIM(PUT(INTNX('MONTH',TODAY(),0,'B'),ddmmyys10.)));
CALL
SYMPUT('MonthEnd',TRIM(PUT(INTNX('MONTH',TODAY(),0,'E'),ddmmyys10.)));
RUN;
%PUT &MonthStart.;
%PUT &MonthEnd.;
PROC SQL;
CREATE TABLE CURRENT_MONTH_ACTIVITY AS
SELECT * FROM MONTH_END_BASE
WHERE ACTIVITY_DATE >= '&MonthStart.' AND ACTIVITY_DATE <= '&MonthEnd.' ;
QUIT;
Thanks in advance!
You can use the INTCK function to check for when the month range from the current date to the activity date is zero.
where INTCK('MONTH', today(), activity_date) = 0;
An alternative would be to use macro to 'code-gen' directly the between points. You don't need a data step to populate a macro variable that is later used.
Example:
data have;
do activity_date = today() - 365 to today() + 365;
output;
end;
format activity_date yymmdd10.;
run;
data want;
set have;
where intck('MONTH', today(), activity_date) = 0;
run;
data want;
set have;
where activity_date
between
%sysfunc(INTNX(MONTH, %sysfunc(today()), 0, B))
and
%sysfunc(INTNX(MONTH, %sysfunc(today()), 0, E))
;
run;
I agree with Tom. Probably the variable activate_date is a numeric type with date format, then the solution is assign to MonthStart and MonthEnd a numeric value.
DATA _NULL_;
CALL SYMPUT('MonthStart',INTNX('MONTH',TODAY(),0,'B'));
CALL SYMPUT('MonthEnd',INTNX('MONTH',TODAY(),0,'E'));
RUN;
%PUT &MonthStart.;
%PUT &MonthEnd.;
PROC SQL;
CREATE TABLE CURRENT_MONTH_ACTIVITY AS
SELECT * FROM MONTH_END_BASE
WHERE ACTIVITY_DATE >= &MonthStart. AND ACTIVITY_DATE <= &MonthEnd. ;
QUIT;
i connected using
proc sql;
connect to odbc as odbc("......");
create table work.market as select distinct * from connection to odbc(
select distinct C.Product#, A.county, B.DT, profit2, Rev2)
From Mtable.duv A, Ttable.duv B, otable C
Where B.Product# = C.Product#
and B.Product# = A.Product#
and B.Dt = C.Dt
and B.dt between A.dt_start and dt_end
and B.dt between 20140331 and 20170630
);
disconnect from odbc;
quit;
data work.smallmarket;
set work.market;
where country=Nigeria;
NetMargin=profit2/Rev2;
keep Product# NetMargin DT;
run;
1) if DT is my date, how do I change the date format from YYYYMMDD to a SAS date format like 01Jan1960? When I run the above I get my data but the dates come out as 20170630 for example. How can i convert by date column to show in the format 30Jun2017. I posted how I got my initial data set "work.market" just in case that is part of the issue. Sorry can't post the log. Can you please help?
If you want to convert to a SAS date format, you have two places to do that.
First, you can do it in the create table statement; that is a SAS statement, not a SQL Server/whatever statement.
proc sql;
connect to odbc as odbc("......");
create table work.market as select Product#, county, dt format=date9.,profit2, rev2
from connection to odbc(
select distinct Product#, county, DT, profit2, Rev2);
The second place you can do it is in the data step following.
data work.smallmarket;
set work.market;
where country=Nigeria;
format dt date9.;
NetMargin=profit2/Rev2;
keep Product# NetMargin DT;
run;
I have a database that has startDate and endDate. I am trying to run this simple script to find and replace certain dates. Here is my script:
SET startDate = '2012-10-11 07:00'
AND
endDate = '2012-10-13 20:00'
where startDate = '2012-10-12 07:00'
AND
endDate = '2012-10-14 20:00'
I run it and receive this error:
Incorrect syntax near '='.: SET startDate => '2012-10-11 07:00' AND endDate = '2012-10-13 20:00' where startDate = '2012-10-12 07:00' AND endDate = '2012-10-14 20:00'
I really have no idea why it's not running correctly, but hopefully one of you clever bod's here will be able to point out my incredibly dumb mistake!
Here's hoping! =0)
you need to separate your columns to update with a comma rather than AND:
UPDATE YourTable
SET startDate = '2012-10-11 07:00',
endDate = '2012-10-13 20:00'
WHERE startDate = '2012-10-12 07:00'
AND endDate = '2012-10-14 20:00'
You should also use a culture insensitive date format like 'yyyyMMdd hh:mm:ss', e.g. your date 2012-10-11 07:00, would be interpretted as 11th October by some cultures, and 10th November by others.
Example on SQL Fiddle of why not use yyyy-mm-dd dates