SQL date with fixed day and month but relative year - sql

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.

Related

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.

Maximo UI SQL Select Month

I am trying to write a query using SQL in the Maximo 7.5 UI advanced search function which will return data from the month before the month in which the query was run. I want to save this query and make it available to users who will run the query without editing it. For example, if a user ran the saved query on 1/25/2019, the query would return all records for which the date was any day in December 2018. I have previously used "where actfinish >= sysdate-30" but the length on months varies and I cannot rely on the users (who do not write SQL) to always run the query on the first day of each month, so I need the query to filter by the previous month. The field I am filtering on is a DATE field, but in the DB it looks like DD-MMM-YY.
Your current where actfinish >= sysdate-30 will return data from the current month, as well as the issues you mentioned.
You can do something like:
where actfinish >= add_months(trunc(sysdate, 'MM'), -1)
and actfinish < trunc(sysdate, 'MM')
The trunc(sysdate, 'MM') gives you midnight on the first day of the current month. The first clausesubtracts a month from that, so gives you midnight on the first day of the previous month; the second clause prevent any record from this month being included.
You can check what those evaluate to by querying the terms outside your real query:
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
select sysdate,
add_months(trunc(sysdate, 'MM'), -1) as month_from,
trunc(sysdate, 'MM') as month_to
from dual;
SYSDATE MONTH_FROM MONTH_TO
------------------- ------------------- -------------------
2019-01-25 12:59:53 2018-12-01 00:00:00 2019-01-01 00:00:00
The alter session is just to make the client format the results in a particular way, instead of explicitly doing to_char().
When you said "in the DB it looks like DD-MMM-YY", it doesn't actually look like that in the database; when you query the date values your client is formatting the dates like that, so your NLS_DATE_FORMAT is probably set to the still-default DD-MON-RR model. (And it's MON in Oracle, not MMM - see the format model elements in the docs.)
Your solution will depend on the type of database that is being used.
For SQL Server, we have used logic along the following lines:
actfinish between dateadd(day,1,eomonth(dateadd(month,-2,getdate()))) and eomonth(dateadd(month,-1,getdate()))
(identify the last day of the previous month and the last day of the month before that + 1 day)
For Oracle, the equivalent would be:
trunc(actfinish,'MONTH') = add_months(trunc(sysdate,'MONTH'),-1)
(identify the year and month associated with last month and compare that against the target date components - trunc month function removes the time and day of month components so making comparisons easier)
I have previously used "where actfinish >= sysdate-30" but the length
on months varies.
By "length of month", do you mean the number of days for each month (e.g. 30, 31, 28, 29) or just a formatting issue with the month? If I understood your question correctly, you can convert the date to character then convert that to date and Oracle will take care of the change in the number of days. For example, something like:
where to_date(to_char(actfinish, 'mm/dd/yyyy')) >= to_date(to_char(sysdate, 'mm/dd/yyyy'))-30
or
where to_date(to_char(actfinish), 'mm/dd/yyyy') >= to_date(to_char(sysdate), 'mm/dd/yyyy')-30
I don't have Maximo installed on my personal laptop so you can try the two I listed above.

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

In Oracle SQL, how to get the time for only this current week?

I have a query , where I want to obtain some data for different time durations (this month, this week, etc).
For the "this week" column, I want it to get all the data from the most recent Monday until now. How would I do this?
I have the following SQL so far :
WHERE prla.CREATION_DATE >= SYSDATE - ?
trunc(sysdate, 'iw') is what you're after. IW is the format mask used for Monday of the week the specified date is in (as Monday is the ISO standard for the start of the week). E.g.:
with dates as (select trunc(sysdate, 'mm') - 10 + level dt
from dual
connect by level <= 40)
select dt
from dates
where dt >= trunc(sysdate, 'iw')
and dt <= sysdate; -- only needed if the dates in the column could be beyond now.
Yeah that will do: But it is better to use sysdate-8. Because if the current day is same as your searching day, it will return the current date. For Eg.
select next_day(sysdate-7,'WED') from dual;
OUTPUT
19-AUG-15
Whereas the below one will give you the last week
select next_day(sysdate-8,'WED') from dual;
OUTPUT
12-AUG-15
You should truncate the current date.
TRUNC(SYSDATE, 'DAY')
This should give you the first day of the week, which is Monday in lot of countries.
If it's giving you the previous Sunday instead you should do this.
TRUNC(SYSDATE, 'DAY')+1
I found out to do this now:
select next_day (sysdate-7, 'MONDAY') Last_Monday from dual;
So in my case, we can remove the SYSDATE subtraction and it is simply :
prla.CREATION_DATE >= next_day (sysdate-7, 'MONDAY')
source

Get first and last date of a month given any date

I have a date in oracle in yyyy-mm-dd format. Is it possible to get from this the following:
1.The exact date 1 yr ago in yyyy-mm-dd format (so : 2013-02-01--> 2012-02-01 and 2013-02-28--> 2012-02-29)
2.The corresponding start date and end date of the same month in yyyy-mm-dd format
Try this:
SELECT
TRUNC(DATE '2013-02-01', 'MM') - INTERVAL '1' YEAR AS one_year_ago_first_day,
LAST_DAY(TRUNC(DATE '2013-02-28', 'MM') - INTERVAL '1' YEAR) AS one_year_ago_last_day,
TRUNC(DATE '2013-02-11', 'MM'),
LAST_DAY(DATE '2013-02-11')
FROM
dual;
Basically, you can get the first day of a month by using TRUNC with MM model format, so everything after month will be truncated (so day will be set to 1).
LAST_DAY - this one returns the date of the last day in the month of the date given as a parameter.
You can also use INTERVAL datatype and subtract it from given date.