Next Occurance of day of next week (Specifically, the next occurance of Wednesday) based on the current date - sql

In Oracle SQL Developer, how does one determine the calendar date of the next occurrence of Wednesday, based on the current date. I have searched and seen many examples for Ruby, PHP, MYSQL, but not for oracle sql. I read this article about DATETIME calculations, but these we have not gone over in class. We are working with date conversion, case, when, timestamps, and intervals but I'm not sure how to go about this problem.

Nex_day function will return the date of the first weekday, specified as the second parameter of the function, later than a date specified as the first parameter of the function. For example:
SQL> select next_day(sysdate, 'WEDNESDAY') next_day
2 from dual
3 ;
NEXT_DAY
-----------
05-DEC-2012

You can use DATE function called NEXT_DAY
Try this
SELECT NEXT_DAY(SYSDATE,'WEDNESDAY') "Next WED"
FROM DUAL ;

Related

Hive start of week on Sunday?

I'm trying to get the start of the week (Sundays, as a date) for a given date. This works except on Sundays since the day of the week origin begins on Monday:
SELECT DATE_SUB(FROM_UNIXTIME(UNIX_TIMESTAMP(CURRENT_DATE(), 'yyyy-MM-dd')), CAST(FROM_UNIXTIME(UNIX_TIMESTAMP(CURRENT_DATE(), 'yyyy-MM-dd'), 'u') AS INT))
The function above would return '2018-04-15' for a supplied date of '2018-04-22' whereas I want '2018-04-22'. Is the only recourse to write an case statement to offset for Sundays? I was hoping there was a nice parameter to FROM_UNIXTIME() that would have the weeks start on Sundays. I didn't find them in these docs:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
You could get the result with a simple trick without case statements.
Calculate the modulus value of the weekday with 7 and you should get your result.
SELECT DATE_SUB(CURRENT_DATE(), CAST(DATE_FORMAT(CURRENT_DATE(),'u')%7 AS INT));

how to get previous month of last day without using date function in oracle10g

How to get previous month of last day without using date function in oracle?
SQL> ed
Wrote file afiedt.buf
1 SELECT LAST_DAY(ADD_MONTHS(sysdate,-1))
2* from dual
SQL> /
LAST_DAY(
---------
30-JUN-14
But I want without using date function
Create a calendar table.
Example here:
http://social.technet.microsoft.com/wiki/contents/articles/22776.t-sql-calendar-table.aspx
Also this question:
Calendar table for Data Warehouse
You'll have to adjust the date functions to work in oracle. But this will let you do date logic without the database specific functions after the one-time load.
You haven't specified which functions you can and can't use, or why, so I don't know if this is allowed by whatever constraints you're trying to do this under:
select trunc(sysdate, 'MM') - 1
from dual;
TRUNC(SYSDATE,'MM')-1
---------------------
30-JUN-14
This form of the trunc() function gives you your date "with the time portion of the day truncated to the unit specified by the format model", although that's slightly misleading as you are not restricted to time format elements. Here I've used format model 'MM', so it truncates to the first of the current month. One day before that is the last day of the previous month.
But trunc() is still a date function, depending on your definition; and maybe more importantly it's still Oracle-specific syntax, which you might be trying to avoid for some reason. but then using sysdate wouldn't be allowed either.

Retrieve previous month from date column that contains MONYYYY

I need to change a date value that is coming from a table in the form of May2013 (MonYYYY). The column itself is a VARCHAR
In my select statement, I am looking to retrieve the previous month (Apr2013). I've done some research and found the following, if I were using SYSDATE:
select to_date(add_months(sysdate, 'MONYYY')-1) from dual
How do I make it work for the date structure I have above? I've tried:
select to_date(add_months(date.datetable, MONYYY)-1) from datetable
ADD_MONTHS function needs a date variable as input. So, first you need to convert your varchar column to date type and then apply the add_months function.
SELECT ADD_MONTHS (TO_DATE ('May2013', 'monyyyy'), -1) FROM DUAL;
The return type will be date. In this case, it returns 0th hour of first day of April.

In oracle SQL, how would you obtain the timestamp representing the start of the week?

I'm using an Oracle 9i database and want to obtain, within a function, the timestamp representing the start of the week, i.e. The most recent monday, at 00:00:00.
I am aware that the timestamp representing the start of the current day is TO_TIMESTAMP(SYSDATE).
You can use the function next_day to get that:
SQL> select next_day(sysdate-7, 'MONDAY') FROM DUAL;
NEXT_DAY
---------
29-APR-13
Getting the start of the week should work with trunc (see docs).
So,
select to_timestamp(trunc(sysdate, 'D')) from dual
should work.
However, depending on your NLS settings, the first day of the week for oracle may well be Sunday.
this appears to return Monday before the day of week in question at midnight. to prove out just play around with sysdate and subtract days...
select case when to_Char(sysdate,'d') = 1 then
trunc(sysdate-6)
else
trunc(sysdate - (to_Char(sysdate,'d')-2))
END
from dual;
You can truncate a date to Monday with:
select trunc(sysdate, 'IW') FROM DUAL;

Oracle to_date function with quarter-format

I need to find some records created in a range of quarters. For example, I'm looking for all records created between the 4th quarter of 2008 and the 1st quarter of 2010. I have this in my WHERE-clause:
...and r.record_create_date between to_date('2008 4','YYYY Q')
and to_date('2010 1','YYYY Q')
but Oracle says: ORA-01820: format code cannot appear in date input format. The Q is a valid date format symbol, so I'm not sure what's happened. Is this even a valid way to find values in between calender quarters, or is there a better way?
Also interesting, and possibly related, if I execute this:
select to_date('2009','YYYY') from dual;
The value displayed in my IDE is 2009-08-01. I would have expected 2009-08-04, since today is 2010-08-04.
This:
select to_date('2009 1','YYYY Q') from dual;
of course, fails.
(Oracle 10g)
Oracle says: ORA-01820: format code cannot appear in date input format. The Q is a valid date format symbol, so I'm not sure what's happened.
See the second column of table 2.15 at http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements004.htm#i34948. Not all format elements are allowed when converting to dates, timestamps, etc.
I recommend against using between for date range checks. People often will miss values within the ending day that the expect to be included. So I would translate:
and r.record_create_date between to_date('2008 4','YYYY Q')
and to_date('2010 1','YYYY Q')
To
and to_date('2008-10-01', 'YYYY-MM-DD') <= r.record_create_date
and record_create_date < to_date('2010-04-01', 'YYYY-MM-DD') -- < beginning of 2Q2010.
Someone asked the same question on OTN: http://forums.oracle.com/forums/thread.jspa?threadID=1081398&tstart=255
The crux of the issue is that you can not specify "Q" in the TO_DATE function.
Given that you're already specifying a portion of the date, why not provide the entire date? Mind too that to_date('2010 1','YYYY Q') would give you Jan 1st, 2010 when you really want March 31st, 2010... at a second to midnight.
Since the relationship between quarters to months is one-to-many, it doesn't make sense to do TO_DATE('2008 1', 'yyyy q'); what date should be returned? The first of the quarter, the end of the quarter, ...? (On the other hand, converting a date to a quarter - like TO_CHAR(SYSDATE, 'yyyy q') makes sense because a specific date only exists in one quarter.)
So, if you do want a query that looks for a date that falls between two quarters, you will have to "rolll your own" (explicitly stating the dates of the start/end of a quarter.)
As a side note, in case anyone is considering not using TO_DATE please do not use things like: WHERE date_value BETWEEN 'date string1' and 'date string2' without the TO_DATE function. It assumes a default date format and under certain situations can avoid potentially useful indexes altogether.
Below is one example where the same query can have a different result.
select sysdate from dual where sysdate between '1-Jan-10' and '31-Dec-10';
SYSDATE
---------
04-AUG-10
SQL> alter session set nls_date_format = 'YYYY-MM-DD';
Session altered.
SQL> select * from dual where sysdate between '1-Jan-10' and '31-Dec-10';
no rows selected
(Notice that in the second instance no error is returned. It just assumes Jan 10, 0001 and Dec. 10th, 0031.)
I think the best way is to just input the quarter start date and quarter end dates without even bothering with to_date. I think if you use
between '1-Jan-10' and '31-Dec-10'
for example, then you don't (in Oracle I believe) need to_date and it isn't much more difficult than typing in the quarter number
To calculate in Oracle the first day of a quarter and the last day of a quarter from the year and quarter:
I Use the fact
start_month= -2 + 3 * quarter
last_month = 3 * quarter
variable v_year number
variable v_quarter number
exec :v_year :=2017
exec :v_quarter:=4
select :v_year as year,
:v_quarter as quarter,
to_date(:v_year||to_char(-2+3*:v_quarter,'fm00'),'yyyymm') as quarter_start,
last_day(to_date(:v_year||to_char(3*:v_quarter,'fm00')||'01 23:59:59','yyyymmdd hh24:mi:ss')) as quarter_end
from dual a;
YEAR|QUARTER|QUARTER_START |QUARTER_END
2017| 4|2017-10-01 00:00:00|2017-12-31 23:59:59