Oracle SQL - Using SysDate to create a specific date - sql

I need to automate a report that will always the first day of the current month and year in the WHERE caluses.
"YYYY-MM-01"
I am trying to achieve the following but sadly, I can't get anything to work using To_Char/ To_Date/SysDate.
to_date(SYSDATE('YYYY-MM') + '-01', 'yyyy-mm-dd')
Thank you

To get the first day of the current month (as a DATE), simply:
trunc(sysdate,'MON')
or, formatted:
to_char(trunc(sysdate,'MON'),'yyyy-mm-dd')

The string concatenation operator in Oracle is ||, not +. And SYSDATE is a constant not a function:
to_date(to_char(SYSDATE, 'YYYY-MM') || '-01', 'yyyy-mm-dd')
By the way, you can also do this calculation as:
trunc(sysdate - extract(day from sysdate) + 1)
That is, subtract the day of the month and add one. That way, you don't have to mess with fiddly date/character formats.

Related

SQL date with fixed day and month but relative year

I've created a report in BusinessObjects WEBI but I would like to customize the underlying SQL so that the year in the date range changes based on when the query is run, leaving the day and month unchanged
This example ...
WHERE
ACT_ENDDT BETWEEN '01-10-2019 00:00:00' AND '30-09-2020 00:00:00'
... is desirable if I ran the query now (current year -1 AND current year, respectively) but if I were to run this query in 2021 I want those years to change to 2020 and 2021, respectively, keeping the day and months the same (10/1 and 9/30).
I searched through a few resources like sqltutorial and w3schools but I'm barely a novice at this and can't wrap my head around how to make it work. I also tried the solution provided here in thread 28707795 as such:
ACT_ENDDT BETWEEN DATEFROMPARTS(YEAR(getdate())-1,10,1) AND DATEFROMPARTS(YEAR(getdate()),9,30)
... but end up with a message that DATEFROMPARTS is an invalid identifier.
Is there a way to hard code part of the date and have a modifier attached to it for just the year, e.g. ... BETWEEN '01-10-'&[*currentyear* - 1] ...?
Thanks.
You can use date artithmetics like this:
where act_enddt between trunc(sysdate, 'year') - interval '3' month
and trunc(sysdate, 'year') + interval '9' month - interval '1' day
I wonder whether a half-open interval may also be helpful:
where act_enddt >= trunc(sysdate, 'year') - interval '3' month
and act_enddt < trunc(sysdate, 'year') + interval '9' month
The difference between the two expressions is that the latter allows dates between October 30th at 00:00 and the end of that day. If your dates have no time component, this does not make a difference (and the second expression is a bit neater).
You can use extract() to extract the year portion of sysdate, do arithmetic on it, like subtracting one, concatenate the month and day portion to complete it to be a date representation and convert this string to a date with to_date().
That's
to_date(extract(YEAR FROM sysdate) - 1 || '-10-01', 'YYYY-MM-DD')
for your lower and
to_date(extract(YEAR FROM sysdate) || '-09-30', 'YYYY-MM-DD')
for your upper boundary.

Using Case Statement in Where Clause ___ Using date ranges with BETWEEN

I am trying to filter a date to a specific range depending on whether or not we have passed the first weekday of the current month.
Oracle seems to not like that I am using BETWEEN.
WHEN
TO_DATE(myDate,'YYYYMMDD')=CASE WHEN TO_DATE(SYSDATE-1) - TO_DATE(last_day(add_months(sysdate, -1))+6)>0
THEN
TO_DATE(last_day(add_months(sysdate, -1))+1, 'YYYYMMDD') --AND to_date(TRUNC(SYSDATE) - 1, 'YYYYMMDD')
Else
TO_DATE(last_day(add_months(sysdate, -2))+1, 'YYYYMMDD') --AND to_date(TRUNC(SYSDATE) - 1, 'YYYYMMDD')
END
Please let me know how to correct this.
If you want dates that are equal to or after the first monday of the current month, you can do:
to_date(my_date, 'YYYYMMDD') >= next_day(trunc(sysdate, 'MM') - 1, 'MONDAY')
trunc(sysdate, 'MM') - 1 gives you the last day of the previous month. Then next_day(..., 'MONDAY') gives you the following Monday.
You can change the day name according to what your definition of a week day is. Also, it is worth noting that the day name (the second argument to next_day() must be provided in the language of your session.

PostgreSQL convert month string to start and end dates of month

Is it possible to convert e.g. string "201701" to dates '2017-01-01' and '2017-01-31' in PostgreSQL?
So for:
"201701" get '2017-01-01' and '2017-01-31'
"201702" get '2017-02-01' and '2017-02-28'
"201703" get '2017-03-01' and '2017-02-31'
etc
You may use the TO_DATE function, and append the day component using string concatenation, something like this:
SELECT
TO_DATE('201702' || '01', 'YYYYMMDD') AS first,
(TO_DATE('201702' || '01', 'YYYYMMDD') + INTERVAL '1 month') -
INTERVAL '1 day' AS last;
The above trick just adds 01 to form the first of the month. For the last day of the same month, it first adds one month to the first, to get the first of the next month, then rolls back one day to get the last of the current month.
Demo
The above answer by Tim Biegeleisen works, but here's an alternative.
The to_date() function converts a string literal to a date value.
sample usage is : to_date(text,format);
SELECT to_date('201701','YYYYMMDD');
(EDITED)
You can also use date_trunc which is a part of PostgreSQL. It does the same as the above one.
select date_trunc('month', current_date) , date_trunc('month', CURRENT_DATE) + interval '1 month - 1 day';
Code Example Live Demo

Dateadd and Datediff function in oracle

I want to use Oracle but DATEDIFF and DATEADD function doesn't work in Oracle DB.
How to write below mentioned code in Oracle?
datediff('QUARTER', pr.StartDate, SYSDATE)
datediff('MONTH', pr.StartDate, SYSDATE)
The best thing to do in this case is to use Oracle's MONTHS_BETWEEN() function.
Instead of:
datediff('QUARTER', pr.StartDate, SYSDATE)
you would use:
MONTHS_BETWEEN(pr.startdate, SYSDATE) / 3
and instead of:
datediff('MONTH', pr.StartDate, SYSDATE)
you would use:
MONTHS_BETWEEN(pr.startdate, SYSDATE)
Keep in mind that MONTHS_BETWEEN() will return fractions of months, so use TRUNC() or ROUND() if you need an integer number.
Of course, if you need days instead of months, you can simply subtract one date from another, e.g., SYSDATE - pr.startdate or vice-versa.
If you need to add days to a date, you can simply to this:
pr.startdate + 1 -- where 1 is the number of days
And if you need to add or subtract months, use the ADD_MONTHS() function - unlike INTERVALs this function is safe to use in leap years.
Hope this helps.
These do not have simple exact equivalents because of the semantics of datediff(). It counts the number of "boundaries" between two date/times.
I believe these are semantically equivalent:
trunc(months_between(trunc(pr.StartDate, 'Q'), trunc(sysdate, 'Q')) / 3)
months_between(trunc(pr.StartDate, 'MONTH'), trunc(sysdate, 'MONTH'))
Because of the truncation to the first day of the quarter/month, these should not be returning fractions.

Oracle query concatenate date

I have the following query:
select *
from mytable
where to_char(mydate,'mm/dd/yyyy') between ('05/23/2013')
and ('06/22/2013')
I need to change it to make dynamically so that I won't modify it every month from 05/23/2013 to 06/23/2013 for example:
('05/23/' + (select to_char(sysdate, 'yyyy') from dual))
but this is giving an error. Any suggestions?
What I need to do: Every month I need to run this query to get the records between 23rd of this month and 23rd of the last month.
Oracle uses || as the concatenation operator:
('05/23/' || (select to_char(sysdate, 'yyyy') from dual))
BTW, David is right. If you really want to compare string representations of dates (but why?), use a date format that is ordered the same way as dates:
to_char(mydate,'yyyy/mm/dd')
You're performing a comparison on strings, not on dates, so your code doesn't work the way you think it does.
Based on the string logic, "05/23/2000" is between "05/22/2013" and "06/24/2000".
Keep the data types as date and Oracle will get the comparison right.
Possibly what you want is:
select *
from my_table
where mydate >= add_months(trunc(sysdate,'MM'),-1)+22 and
mydate < trunc(sysdate,'MM')+22
but it's difficult to tell without a description of what the requirement actually is.
How about this one?
SELECT '(''05/23/'''||to_char(sysdate, 'yyyy')||'''' FROM DUAL
Have not testet because I have no Oracle database right now, needs checking for quote escapes...
Do you need exact days from the month? You can also substract days from sysdate:
SELECT (sysdate - 30) FROM DUAL
You may also use concat function
concat('05/23/', (select to_char(sysdate, 'yyyy') from dual))