SAS Proc SQL function in where clause for only current week - date

I have some data in week-date-time format ie 14dec2020 00:00:00:0000. I am using SAS and a proc sql query
This data contains many weeks worth of data but i was curious if theres in way to only pull data relevant to only current week? IE today is 17dec2020 so i would want to only pull data for the week of 14dec2020. if today was 22dec2020 then i would want it to pull data for the week of 21dec2020.
Here is one of the many queries i have tried.
data have;
today = today();
wkday = weekday(today);
start = today - (wkday - 1);
end = today + (7 - wkday);
length cstart cend $30;
cstart = put(start, date9.) || ' 00:00:00.0000' ;
cend = put(end, date9.) || ' 00:00:00.0000' ;
call symput('start', cstart);
call symput('end', cend);
run;
Proc Sql;
connect to odbc (environment=x user=y p=z);
create table basic.curweek as select * from connection to odbc
(select year, month, week, store, sales, SKU
from datatable
where (&start. <= week <= &end.)
order by sku);
disconnect from odbc;
quit;
Thanks to the help of the great people below i have gotten to this state. But am still facing some syntax errors.
Any help here would be greatly appreciated!!

Use intnx() to align both the datetime of interest and today's datetime to the start of the week.
proc sql;
create table want as
select *
from table
where intnx('dtweek', date, 0, 'B') = intnx('dtweek', datetime(), 0, 'B')
;
quit;

As others have pointed out - if you are using SQL pass-thru, you need to use date functions that exist in your "flavor" of SQL. SAS specific functions will not work, and in particular SAS function "today()" has no meaning in the SQL you are working with.
The approach I would take is:
in a SAS datastep - get today's date
use today's date to calculate beginning and end of the week
convert beginning/end dates to character strings
(string will depend on how dates are formatted in your sql database - date or datetime)
use character strings to create macro variables
feed macro variables into sql pass-thru query to subset dates wanted
Below is some example code. It might not get you all the way there, but could give you some more ideas to try.
data have;
today = today(); *** TODAYs DATE ***;
wkday = weekday(today); *** WEEK DAY NUMBER FOR TODAY, POSSIBLE VALUES ARE 1-7 ***;
start = today - (wkday - 1); *** CALCULATE SUNDAY ***;
end = today + (7 - wkday); *** CALCULATE SATURDAY ***;
*** UNCOMMENT AND USE BELOW IF WEEK START/END IS MON-FRI ***;
*start = today - (wkday - 2); *** CALCULATE MONDAY ***;
*end = today + (6 - wkday); *** CALCULATE FRIDAY ***;
*** REPRESENT DATES AS DATE-TIME CHARACTER STRING - SURROUNDED BY SINGLE QUOTES ***;
cstart = "'" || put(start, date9.) || ' 00:00:00.0000' || "'";
cend = "'" || put(end, date9.) || ' 00:00:00.0000' || "'";
*** USE CHARACTER VARIABLES TO CREATE MACRO VARIABLES ***;
call symput('start', cstart);
call symput('end', cend);
run;
*** IN SQL PASS-THRU, USE MACRO VARIABLES IN WHERE STATEMENT TO SUBSET ONE WEEK ***;
Proc Sql
connect to odbc (environment=x user=y p=z);
create table basic.curweek as select * from connection to odbc
(select year, month, week, store, sales, SKU
from datatable
where (&start. <= week and week <= &end.)
order by sku);
disconnect from odbc;
quit;

Related

SQLite query to compare dates

I have two text columns (valid_from and valid_to) in a table (history) in SQLite database in which I am storing date in dd/MM/yyyy format.
Now I am running following query to fetch all the records between June 1, 2018 to June 30, 2018, but I am not getting any results:
Try 1:
SELECT * FROM history WHERE valid_from >= datetime('01/06/2018') AND valid_to <= datetime('30/06/2018');
Try 2:
SELECT * FROM history WHERE cast(strftime('%Y%m%d', valid_from) as integer) >= cast(strftime('%Y%m%d', '01/06/2018') as integer) AND cast(strftime('%Y%m%d', valid_to) as integer) <= cast(strftime('%Y%m%d', '30/06/2018') as integer);
Nothing fetched the records. Am I missing something?
You should always store your date information in SQLite in an ISO format, where the year comes before the month, which comes before the day. The reason for this is that in SQLite dates are just stored as plain text, and your current format won't sort properly. As a workaround, you may try the following query:
SELECT *
FROM history
WHERE
SUBSTR(valid_from, 7, 4) || '/' || SUBSTR(valid_from, 4, 2) ||
'/' || SUBSTR(valid_from, 1, 2)
BETWEEN '2018/06/01' AND '2018/06/30';
Here we are just building the correct date format for each date. But again, the best long term solution is to fix your date data.

What is the Impala SQL equivalent function of NEXTDAY in Netezza?

I have a SELECT statement that I am trying to convert from Netezza SQL to Impala SQL. The output looks something like 140612, which is a date that is obtained by subtracting 7 from the current date and then pulling out the monday of that week.
I need to have this readable for Impala, then format it, then turn it into a string.
The query is :
TO_CHAR(next_day(DATE(a.date)-7, 'Monday'), 'YYMMDD') AS START_DATE
Assuming a.date is a timestamp, and T is the day of the week (1 = Sunday, 7 = Saturday; for your example above, Monday = 2, so T = 2) you should be able to use use
date_add(a.date, 7 - pmod(dayofweek(a.date) - T, 7));
in place of next_day in the above query. Check out the documentation on Impala's built-in date and time functions for more detail.

MS Access : Dealing with today's date in calculated field expression

Hi I am creating a table in MS Access to store the details of children in a school.
I have a field called YearGroup which needs to calculate the school year they are in based on their date of birth and whether they have been moved up or down a year.
I.e. if the expression deems they are six years old they should be placed in year 2. If they were moved down or up a year they should be in year 1 or 3 (this is based on another field in the table called YearModifier).
The code I have at the moment is this:
Year(Now()) - IIf(Month([DOB]) > 8, Year([DOB]) + 6 + [YearModifier], Year([DOB]) + 5 + [YearModifier])
My problem is that Year(Now()) is returning as invalid expression. Lots of websites have recognised using the Now() function and also I've tried Date() but nothing seems to be accepted by Access (The version is 2010).
What is going on? How can I get today's date in a calculated field expression?
Thanks
Try creating a query with all of the fields from your table, and then add an extra field YearGroup: Year(Now()) - IIf(Month([DOB]) > 8, Year([DOB]) + 6 + [YearModifier], Year([DOB]) + 5 + [YearModifier])
It appears that Date functions can't be used in calculated columns in tables.
You could use this to get the year, which might work in field expressions:
format(date(),"yyyy")
About your function (which I have re-written very slightly)
Year( Now() )
- Year([DOB])
- IIf( Month([DOB]) > 8
, 6
, 5 )
+ [YearModifier]
however!
I don't think you want to use now(). Which year they are in depend on their age at the 1st Sept at the start of the current academic year not now! Ok now will work until 31/dec/2015, so I must assume you will not be using the function after this date!
If you are you must use 2015 not Now().
Ok?
You can calculate the age of the children with a simple function:
Public Function AgeSimple( _
ByVal datDateOfBirth As Date) _
As Integer
' Returns the difference in full years from datDateOfBirth to current date.
'
' Calculates correctly for:
' leap years
' dates of 29. February
' date/time values with embedded time values
'
' DateAdd() is used for check for month end of February as it correctly
' returns Feb. 28. when adding a count of years to dates of Feb. 29.
' when the resulting year is a common year.
' After an idea of Markus G. Fischer.
'
' 2007-06-26. Cactus Data ApS, CPH.
Dim datToday As Date
Dim intAge As Integer
Dim intYears As Integer
datToday = Date
' Find difference in calendar years.
intYears = DateDiff("yyyy", datDateOfBirth, datToday)
If intYears > 0 Then
' Decrease by 1 if current date is earlier than birthday of current year
' using DateDiff to ignore a time portion of datDateOfBirth.
intAge = intYears - Abs(DateDiff("d", datToday, DateAdd("yyyy", intYears, datDateOfBirth)) > 0)
End If
AgeSimple = intAge
End Function
Then your expression would be something like this (ignoring the modifier):
ClassYear: IIf(AgeSimple([DOB]) > 6, 2, 1)

removing day portion of date variable for time series SAS

I'm having some frustration with dates in SAS.
I am using proc forecast and am trying make my dates spread evenly. I did some pre-processing wiht proc sql to get my counts by month but my dates are incorrect.
Though my dataset looks good (b/c I used format MONYY.) the actual value of that variable is wrong.
date year month count
Jan10 2010 1 100
Feb10 2010 2 494
...
..
.
The Date value is actually the full SAS representation of the date (18267), meaning that it includes the day count.
Do I need to convert the variable to a string and back to a date or is there a quick proc i can run?
My goal is to use the date variable with proc forecast so I only want Month and year.
Thanks for any help!
You can't define a date variable in SAS (so the number of days passed from 1jan1960) excluding the day.
What you can do is to hide the day with a format like monyy. but the underlying number will always contain that information.
Maybe you can use the interval=month option in proc forecast?
Please add some detail about the problem you're encountering with the forecast procedure.
EDIT: check this example:
data past;
keep date sales;
format date monyy5.;
lu = 0;
n = 25;
do i = -10 to n;
u = .7 * lu + .2 * rannor(1234);
lu = u;
sales = 10 + .10 * i + u;
date = intnx( 'month', '1jul1991'd, i - n );
if i > 0 then output;
end;
run;
proc forecast data=past interval=month lead=10 out=pred;
var sales;
id date;
run;

How can I compare two datetime fields but ignore the year?

I get to dust off my VBScript hat and write some classic ASP to query a SQL Server 2000 database.
Here's the scenario:
I have two datetime fields called fieldA and fieldB.
fieldB will never have a year value that's greater than the year of fieldA
It is possible the that two fields will have the same year.
What I want is all records where fieldA >= fieldB, independent of the year. Just pretend that each field is just a month & day.
How can I get this? My knowledge of T-SQL date/time functions is spotty at best.
You may want to use the built in time functions such as DAY and MONTH. e.g.
SELECT * from table where
MONTH(fieldA) > MONTH(fieldB) OR(
MONTH(fieldA) = MONTH(fieldB) AND DAY(fieldA) >= DAY(fieldB))
Selecting all rows where either the fieldA's month is greater or the months are the same and fieldA's day is greater.
select *
from t
where datepart(month,t.fieldA) >= datepart(month,t.fieldB)
or (datepart(month,t.fieldA) = datepart(month,t.fieldB)
and datepart(day,t.fieldA) >= datepart(day,t.fieldB))
If you care about hours, minutes, seconds, you'll need to extend this to cover the cases, although it may be faster to cast to a suitable string, remove the year and compare.
select *
from t
where substring(convert(varchar,t.fieldA,21),5,20)
>= substring(convert(varchar,t.fieldB,21),5,20)
SELECT *
FROM SOME_TABLE
WHERE MONTH(fieldA) > MONTH(fieldB)
OR ( MONTH(fieldA) = MONTH(fieldB) AND DAY(fieldA) >= DAY(fieldB) )
I would approach this from a Julian date perspective, convert each field into the Julian date (number of days after the first of year), then compare those values.
This may or may not produce desired results with respect to leap years.
If you were worried about hours, minutes, seconds, etc., you could adjust the DateDiff functions to calculate the number of hours (or minutes or seconds) since the beginning of the year.
SELECT *
FROM SOME_Table
WHERE DateDiff(d, '1/01/' + Cast(DatePart(yy, fieldA) AS VarChar(5)), fieldA) >=
DateDiff(d, '1/01/' + Cast(DatePart(yy, fieldB) AS VarChar(5)), fieldB)
Temp table for testing
Create table #t (calDate date)
Declare #curDate date = '2010-01-01'
while #curDate < '2021-01-01'
begin
insert into #t values (#curDate)
Set #curDate = dateadd(dd,1,#curDate)
end
Example of any date greater than or equal to today
Declare #testDate date = getdate()
SELECT *
FROM #t
WHERE datediff(dd,dateadd(yy,1900 - year(#testDate),#testDate),dateadd(yy,1900 - year(calDate),calDate)) >= 0
One more example with any day less than today
Declare #testDate date = getdate()
SELECT *
FROM #t
WHERE datediff(dd,dateadd(yy,1900 - year(#testDate),#testDate),dateadd(yy,1900 - year(calDate),calDate)) < 0