Calculation with WEEK in oracle - sql

I am comparing two dates in oracle where I stuck at one point in which I have to compare my week with the current week.
Suppose today is 05-Jan-2015 and it's a first week and input date is 29_Dec-2014 and I'm executing below statement to compare:
ld_week BETWEEN FOCUS_WEEK-4 AND FOCUS_WEEK-1
where:
ld_week is the week from input date (last week of current year)
focus_week is week from current date (first week of next year)
hence (52 BETWEEN (1-4) AND (1-1)) always fails.
I am using below function to calculate the week.
FOCUS_WEEK := to_number(to_char(to_date(focus_day),'WW'));
Please let me know how to deal with it.

Your question is a bit vague. I believe you want to try
trunk(date '2014-12-29', 'd')
between
trunk(sysdate - 4*7 , 'd') and
trunk(sysdate - 1*7 , 'd')
With trunc(date, 'd') you obtain the start date of a week.

Related

First day of the month

WHERE to_date(smz_loanservicing.as_of_date) = last_day(add_months(current_date, -1))
The above will provide data only if the loanservicing.as_of_date occurs on the very last day of the month.
Last month (May 31 2020) the last day of the month fell on Sunday.
Is there a way to get the the first day of the month and say if this particular date occurs between the first and last day of the month, show the date? Essentially there were no activities on Sunday so the data was missed.
I tried
to_date(smz_loanservicing.as_of_date)
between first_day(add_month(current_date,-1))
and last_day(add_months(current_date, -1))`
However I get syntax error.
You seem to want to check if your date column belongs to the current month.
The syntax you use would work in Oracle, so let me assume this is the database that you are running. I also assume that column as_of_date is of datatype date (or timestamp).
What you ask for should be as simple as:
where
as_of_date >= trunc(current_date, 'mm')
and as_of_date < add_months(trunc(current_date, 'mm'), 1)
Actually, your syntax would also work in Snowflake - and so would the above code.
Note: if as_of_date actually is a string, then you need to_date() to convert it.
You could just truncate the date to the month, then you don’t need the know the first or last day.
where trunc(as_of_date, ‘MM’) = trunc(current_date, ‘MM’)

SQL ORACLE Get week numbers from multiple datetime rows

I have 70.000 rows of data, including a date time column (YYYY-MM-DD HH24-MM-SS.).
I want to split this data into 3 separate columns; Hour, day and Week number.
The date time column name is 'REGISTRATIONDATE' from the table 'CONTRACTS'.
This is what I have so far for the day and hour columns:
SELECT substr(REGISTRATIONDATE, 0, 10) AS "Date",
substr(REGISTRATIONDATE, 11, 9) AS "Hour"
FROM CONTRACTS;
I have seen the options to get a week number for specific dates, this assignment concerns 70.000 dates so this is not an option.
You (the OP) still have to explain what week number to assign to the first few days in a year, until the first Monday of the year. Do you assign a week number for the prior calendar year? In a Comment I asked about January 1, 2017, as an example; that was a Sunday. The week from January 2 to January 8 of 2017 is "week 1" according to your definition; what week number do you assign to Sunday, January 1, 2017?
The straightforward calculation below assigns to it week number 0. Other than that, the computation is trivial.
Notes: To find the Monday of the week for any given date dt, we can use trunc(dt, 'iw'). iw stands for ISO Week, standard week which starts on Monday and ends on Sunday.
Then: To find the first Monday of the year, we can start with the date January 7 and ask for the Monday of the week in which January 7 falls. (I won't explain that one - it's easy logic and it has nothing to do with programming.)
To input a fixed date, the best way is with the date literal syntax: date '2017-01-07' for January 7. Please check the Oracle documentation for "date literals" if you are not familiar with it.
So: to find the week number for any date dt, compute
1 + ( trunc(dt, 'iw') - trunc(date '2017-01-07', 'iw') ) / 7
This formula finds the Monday of the ISO Week of dt and subtracts the first Monday of the year - using Oracle date arithmetic, where the difference between two dates is the number of days between them. So to find the number of weeks we divide by 7; and to have the first Monday be assigned the number 1, instead of 0, we need to add 1 to the result of dividing by 7.
The other issue you will have to address is to convert your strings into dates. The best solution would be to fix the data model itself (change the data type of the column so that it is DATE instead of VARCHAR2); then all the bits of data you need could be extracted more easily, you would make sure you don't have dates like '2017-02-29 12:30:00' in your data (currently, if you do, you will have a very hard time making any date calculations work), queries will be a lot faster, etc. Anyway, that's an entirely different issue so I'll leave it out of this discussion.
Assuming your REGISTRATIONDATE if formatted as 'MM/DD/YYYY'
the simples (and the faster ) query is based ond to to_char(to_date(REGISTRATIONDATE,'MM/DD/YYYY'),'WW')
(otherwise convert you column in a proper date and perform the conversio to week number)
SELECT substr(REGISTRATIONDATE, 0, 10) AS "Date",
substr(REGISTRATIONDATE, 11, 9) AS "Hour",
to_char(to_date(REGISTRATIONDATE,'MM/DD/YYYY'),'WW') as "Week"
FROM CONTRACTS;
This is messy, but it looks like it works:
to_char(
to_date(RegistrationDate,'YYYY-MM-DD HH24-MI-SS') +
to_number(to_char(trunc(to_date(RegistrationDate,'YYYY-MM-DD HH24-MI-SS'),'YEAR'),'D'))
- 2,
'WW')
On the outside you have the solution previous given by others but using the correct date format. In the middle there is an adjustment of a certain number of days to adjust for where the 1st Jan falls. The trunc part gets the first of Jan from the date, the 'D' gets the weekday of 1st Jan. Since 1 represents Sunday, we have to use -2 to get what we need.
EDIT: I may delete this answer later, but it looks to me that the one from #mathguy is the best. See also the comments on that answer for how to extend to a general solution.
But first you need to:
Decide what to do dates in Jan before the first Monday, and
Resolve the underlying problems in the date which prevent it being converted to dates.
On point 1, if assigning week 0 is not acceptable (you want week 52/53) it gets a bit more complicated, but we'll still be able to help.
As I see it, on point 2, either there is something systematically wrong (perhaps they are timestamps and include fractions of a second) or there are isolated cases of invalid data.
Either the length, or the format, or the specific values don't compute. The error message you got suggests that at least some of the data is "too long", and the code in my comment should help you locate that.

How to subtract 13 weeks from a date in PL SQL?

I have a date in sql which will always fall on a Monday and I'm subtracting 13 weeks to get a weekly report. I am trying to get the same 13 week report but for last year's figures as well.
At the moment, I'm using the following:
calendar_date >= TRUNC(sysdate) - 91
which is working fine.
I need the same for last year.
However, when I split this into calendar weeks, there will also be a partially complete week as it will include 1 or 2 days from the previous week. I need only whole weeks.
e.g. the dates that will be returned for last year will be 14-Feb-2015 to 16-May-2015. I need it to start on the Monday and be 16-Feb-2015. This will change each week as I am only interested in complete weeks...
I would do this:
Get the date by substracting 91 days as you're already doing.
Get the number of the day of the week with TO_CHAR(DATE,'d')
Add the number of days until the next monday to the date.
Something like this:
SELECT TO_DATE(TO_DATE('16/05/2015','DD/MM/YYYY'),'DD/MM/YYYY')-91 + MOD(7 - TO_NUMBER(TO_CHAR(TO_DATE(TO_DATE('16/05/2015','DD/MM/YYYY'),'DD/MM/RRRR')-91,'d'))+1,7) d
FROM dual
next_day - returns date of first weekday named by char.
with dates as (select to_date('16/05/2015','DD/MM/YYYY') d from dual)
select
trunc(next_day( trunc(d-91) - interval '1' second,'MONDAY'))
from dates;
I want to get next monday from calculated date. In situation when calculated date is monday i have to move back to previous week ( -1 second).

Teradata Change format of Week Number

I'm pretty new to SQL so I hope this isn't a dumb question, tried to google but couldn't find anything.
I'm summing sales of departments per week in SQL and am using TD_SYSFNLIB.WEEKNUMBER_OF_YEAR (trans_dt) to get the week number.
I think everything is working except I'd like to change the format of the weeks to the start date of the week, e.g. week 1 = 1/4/15
Also, i'm not sure how to handle the very first of the year week 0 since I think that should be grouped up with week 52 of last year.
The following date math trick should get you Beginning of Week as an actual date without having to join to the SYS_CALENDAR view or using a function:
SELECT CURRENT_DATE - ((CURRENT_DATE - DATE '0001-01-07) MOD 7) AS BOW;
Starting with TD14 there's NEXT_DAY which returns the following weekday, if you subtract 7 days you get the previous day:
next_day(trans_dt - 7, 'sunday')

SQL +/- number meaning?

I could not find the meaning of the following SQL command:
where date between to_date('2013-03-01', 'yyyy-mm-dd') and trunc(sysdate, 'mm') -1
What does the "-1" mean / does?
The other example is
trunc(months_between(date1, date2))+1
I have searched for this, but could not find a thing.
Thank you for advice!
As others have answered, "date - 1" subtracts one day from the date. Here's more detail on your specific SQL snippets:
where date between to_date('2013-03-01', 'yyyy-mm-dd') and trunc(sysdate, 'mm') -1`
This evaluates to "date between 3/1/2013 and the end of last month"
TRUNC(some date, 'MM') chops the date to the beginning of the month
TRUNC(SYSDATE, 'MM') returns the beginning of the current month
TRUNC(SYSDATE, 'MM')-1 returns the last day of the previous month
trunc(months_between(date1, date2))+1
This is giving the number of full months between date1 and date2, treating any fraction of a month as a whole month. For example, if you gave it the dates 7/28/2013 and 7/29/2013 it would report one month, and it would also report one month if you gave it 7/1/2013 and 7/31/2013.
The MONTHS_BETWEEN function returns, as it implies, the number of months between two dates. The return value will have decimal places - for example a return value of 1.5 means one and a half months.
The TRUNC function, when applied against a numeric, will chop off all its decimals, so TRUNC(1.9999999) will return 1.
+1 is way to add a day to the date
-1 is way to remove a day to the date
In your specific case:
the instruction trunc(sysdate, 'mm') -1 remove one month to the date, in this case is one month before the current date.
the instruction trunc(months_between(date1, date2))+1 compute the difference in month between the two dates and then adds one.
Give a look at this SQLFiddle
it is a lazy way of adding or subtracting day(s)