How to_date function with sysdate - sql

select TO_CHAR(sysdate, 'YEAR')-365 FROM DUAL;
I get error
'invalide number'

See the result of TO_CHAR(sysdate-365, 'YEAR') and then think if you can cast this to a numeric value to be able to subtract 365.
'twenty fourteen' - 365
You probably want the previous year's date:
add_months(sysdate, -12)
Or if you need the year exactly 365 days before today:
extract(year from sysdate - 365)

Your code
select TO_CHAR(sysdate, 'YEAR')-365 FROM DUAL;
doesn't work because you try to make an mathematical operation on string value TO_CHAR(sysdate, 'YEAR') which is not properly.
This will work
select EXTRACT(YEAR from sysdate)-365 FROM DUAL;
result
1650
but it doesn't make sense, so maybe you need this
select EXTRACT(YEAR from sysdate)-1 FROM DUAL;
result
2014

TO_CHAR(sysdate, 'YEAR')
It converts DATE into string. For date arithmetic, do the calculation on the date itself.
For example,
SELECT TO_CHAR(SYSDATE - 365, 'YEAR') FROM DUAL;

Related

ORA-01839: date not valid for month specified, How to avoid leap year issues

I have a table that stores a valid "custom date" for each person. That date may legitimately be Feb 29 of a leap year. The thing is in my SQL for my report I need to pull the "last" mm/dd for from this custom date field for that employee as of the most recent year. This date is never in the future so I can compare the year in the date and if its the current year pull it as is. However if it's any previous year (can go back as far as 1900) I need to instead pull that MM/DD and as of last year. So you can see how this will be a problem since there is no Feb-29-2018.
I'm looking for the best solution on how to handle this. I need it in my select portion and my conditional block where this date I'm trying to derive has to be >= the applydtm date. Here is a sample query to replicate the error. Simply switching the Feb-29 date to Feb-28 will show it working since it doesn't encounter that invalid leap year date. I would be okay with all Feb 29 dates 'converting' to Mar 1st if need be as long as the code is efficient as possible. DB = Oracle 11g
WITH sampledata (actualcustomdtm, textfield, applydtm) AS (
SELECT
TO_DATE('02/29/2012 00:00:00','mm/dd/yyyy hh24:mi:ss'),
'Leap Year',
sysdate
FROM dual
UNION
SELECT
TO_DATE('01/15/2019 00:00:00','mm/dd/yyyy hh24:mi:ss'),
'Non-Leap Year',
sysdate
FROM dual
)
SELECT
actualcustomdtm,
CASE WHEN TO_CHAR(actualcustomdtm, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
THEN TO_CHAR(actualcustomdtm, 'MM/DD/YYYY')
ELSE TO_CHAR(actualcustomdtm, 'MM/DD')||'/'||TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE), -12), 'YYYY')
END AS "LASTACTCSTMDATE",
textfield,
applydtm
FROM sampledata
WHERE applydtm >=
TO_DATE(CASE WHEN TO_CHAR(actualcustomdtm, 'YYYY') = TO_CHAR(SYSDATE, 'YYYY')
THEN TO_CHAR(actualcustomdtm, 'MM/DD/YYYY')
ELSE TO_CHAR(actualcustomdtm, 'MM/DD')||'/'||TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE), -12), 'YYYY')
END, 'MM/DD/YYYY')
I believe this logic does what you want -- getting the most recent anniversary up to or including today's date:
select dte, add_months(dte, 12),
(case when to_char(dte, 'MMDD') > to_char(sysdate, 'MMDD')
then add_months(dte, 12 * (extract(year from sysdate) - extract(year from dte) - 1))
else add_months(dte, 12 * (extract(year from sysdate) - extract(year from dte)))
end)
from (select date '2016-02-29' as dte from dual union all
select date '2018-01-03' from dual
) x;

Query to 'get the records from the actual month' doesn't get me the records that have a bigger day that the current one

I have the following query to get the records from a table from the current month
select *
from
myTable
where
my_date BETWEEN trunc (sysdate, 'mm') AND SYSDATE;
This query works if the records have a lower day compared to the current one
example: if today is 27/10/2016 and I have a record that have this date: 28/10/2016
The record with date 28/10/2016 is not showing
I insert the records using this format TO_DATE( '28/10/2016 18:02:44', 'dd/mm/yyyy hh24:mi:ss')
I want to show all the records from the curren month even if the day is bigger than the actual date
Either:
select *
from
myTable
where
my_date BETWEEN trunc (sysdate, 'mm') AND add_months(trunc (sysdate, 'mm'),1)- 1/(24*3600)
or
select *
from
myTable
where
trunc(my_date,'mm') = trunc (sysdate, 'mm')
The first is sargable, the second is more readable.
If you need the dates in the current month
trunc(my_date, 'mm') = trunc(sysdate, 'mm')
If you need the dates from the current month and on:
my_date >= trunc(sysdate, 'mm')

Current Financial Year to sysdate

I can't seem to find a straightforward sql without delving into PL SQL for always bringing current financial year in which case 01-04-2015 to sysdate. I want this to always update automatically so when it comes next financial year in 01/04/2016 it will bring whatever is held from that date to whenever the report is being run.
If anyone can please shed some light for me. thanks
sql is:
SELECT
PROPERTY.PRO_MANAGINGCOMPANY_DESCR,
PROPERTY.PRO_SCHEME_DESCR,
PROPERTY.PRO_SCHEME,
SUM(REPAIR_CURRENT.REP_ESTIMATED_COST) as "Estimated Cost",
nvl(SUM(REPAIR_CURRENT.REP_INVOICED_COST),SUM(REPAIR_CURRENT.REP_ESTIMATED_COST)) as "Estimated Cost Invoiced",
SUM(REPAIR_CURRENT.REP_INVOICED_COST) as "Invoice Cost",
to_char(REPAIR_CURRENT.REP_RAISED_DATE,'Mon') as "Month",
to_number(to_char(to_date(REPAIR_CURRENT.REP_RAISED_DATE,'dd-mon-yy'),'mm')) as "Month No."
FROM
PROPERTY,
REPAIR_CURRENT,
SERVICE_REQUEST
WHERE
( SERVICE_REQUEST.SRQ_PRO_REFNO=PROPERTY.PRO_REFNO )
AND ( REPAIR_CURRENT.REP_SRQ_NO=SERVICE_REQUEST.SRQ_NO )
AND
(
--PROPERTY.PRO_SCHEME = ( '00054' )
--AND
REPAIR_CURRENT.REP_RAISED_DATE BETWEEN '01-APR-2015' AND sysdate
AND
REPAIR_CURRENT.REP_STATUS <> 'CAN'
)
GROUP BY
PROPERTY.PRO_MANAGINGCOMPANY_DESCR,
PROPERTY.PRO_SCHEME_DESCR,
PROPERTY.PRO_SCHEME,
to_char(REPAIR_CURRENT.REP_RAISED_DATE,'Mon'),
to_number(to_char(to_date(REPAIR_CURRENT.REP_RAISED_DATE,'dd-mon-yy'),'mm'))
If you just want to get the beginning of the fiscal year for the current date:
SELECT TO_DATE('01-04' || CASE
WHEN EXTRACT(MONTH FROM SYSDATE) > 4 THEN
EXTRACT(YEAR FROM SYSDATE)
ELSE
EXTRACT(YEAR FROM SYSDATE)-1
END, 'DD-MM-RRRR') FISCAL_YEAR
FROM DUAL
This works for any date:
REPAIR_CURRENT.REP_RAISED_DATE
BETWEEN Add_Months(Trunc(Add_Months(sysdate,-3),'YYYY'),3)
AND Sysdate
Basically, subtract three months, truncate to the year, and add three months back on.
To just get the financial year for a date, use:
Extract(Year from Add_Months(Trunc(Add_Months(sysdate,-3),'YYYY'),3))
SELECT *
FROM your_table
WHERE datetime >= CASE
WHEN SYSDATE < TRUNC( SYSDATE, 'YEAR' ) + INTERVAL '3' MONTH
THEN TRUNC( SYSDATE, 'YEAR' ) - INTERVAL '9' MONTH
ELSE TRUNC( SYSDATE, 'YEAR' ) + INTERVAL '3' MONTH
END;
Thank you, the following worked! add_months(trunc(sysdate,'year'),3) AND sysdate
thank you all for your input :)
REPAIR_CURRENT.REP_RAISED_DATE BETWEEN '01-APR-2015' AND sysdate
Firstly, '01-APR-2015' is not a DATE it is a string. You must always use TO_DATE along with proper format model to explicitly convert the string into DATE. Or, use the ANSI Date literal as you are not concerned with the time portion. It uses a fixed format 'YYYY-MM-DD'.
Now, coming to your date arithmetic, you could use a CASE expression to evaluate the financial date depending on the year.
REP_RAISED_DATE
BETWEEN
CASE
WHEN
SYSDATE < ADD_MONTHS(TRUNC(SYSDATE, 'YEAR'), 3)
THEN
ADD_MONTHS(TRUNC(SYSDATE, 'YEAR') , -9)
ELSE
ADD_MONTHS(TRUNC(SYSDATE, 'YEAR'), 3)
END
AND SYSDATE
Basically, SYSDATE >= ADD_MONTHS(TRUNC(SYSDATE, 'YEAR'), 3) is to check whether SYSDATE is greater than 1-APR of current year. And, SYSDATE < ADD_MONTHS(TRUNC(SYSDATE, 'YEAR'), 15) is to check whether it is between JAN and MARCH of next year.
For example,
SQL> SELECT
2 CASE
3 WHEN
4 SYSDATE < ADD_MONTHS(TRUNC(SYSDATE, 'YEAR'), 3)
5 THEN
6 ADD_MONTHS(TRUNC(SYSDATE, 'YEAR') ,-9)
7 ELSE
8 ADD_MONTHS(TRUNC(SYSDATE, 'YEAR'), 3)
9 END FINANCIAL_YEAR
10 FROM dual;
FINANCIAL
---------
01-APR-15
For date between JAN and MAR of next year:
SQL> SELECT
2 CASE
3 WHEN
4 DATE '2016-02-01' < ADD_MONTHS(TRUNC(DATE '2016-02-01', 'YEAR'), 3)
5 THEN
6 ADD_MONTHS(TRUNC(DATE '2016-02-01', 'YEAR') ,-9)
7 ELSE
8 ADD_MONTHS(TRUNC(DATE '2016-02-01', 'YEAR'), 3)
9 END FINANCIAL_YEAR
10 FROM dual;
FINANCIAL
---------
01-APR-15
Following SQLreturns start and end date for Financial Year of current date.
SELECT
TO_DATE('01-04' || EXTRACT(YEAR FROM add_months(sysdate, -3)),'DD-MM-RRRR') from_dt ,
TO_DATE('31-03' || EXTRACT(YEAR FROM add_months(sysdate, 9)),'DD-MM-RRRR') to_dt from dual;
For any random date, you can use the following SQL: example for 01-04-2020
SELECT
TO_DATE('01-04' || EXTRACT(YEAR FROM add_months(to_date('01-04-2020','DD-MM-RRRR'), -3)),'DD-MM-RRRR') from_dt ,
TO_DATE('31-03' || EXTRACT(YEAR FROM add_months(to_date('01-04-2020','DD-MM-RRRR'), 9)),'DD-MM-RRRR') to_dt from dual;

Insert date in oracle

When i executed the below query in Oracle
select TO_CHAR((CURRENT_DATE),'DD-Mon-YYYY HH24:MI:SS') from dual;
O/P : 04-Mar-2014 14:25:14
I would like to select current date only without current time as below
select TO_CHAR(trunc(CURRENT_DATE),'DD-Mon-YYYY HH24:MI:SS') from dual;
O/P : 04-Mar-2014 00:00:00
To achieve the only way is to apply function trunc() on the query? Is there any another way?
Edit : Thanks for your ans.Can it be done without any function?(wihout using to_char or trunc)
{sorry for missing this info}
The answer is simply no, there is no function that only gets the date part of the date / time (even current_date or sysdate are functions after all).
You should always use trunc to get the current date, without the time.
It isn't necessary to do a trunc and a to_char together. Keep to_char and don't specify the time part.
This is sufficient:
To get the date as varchar:
select TO_CHAR(CURRENT_DATE,'DD-Mon-YYYY') from dual
To get the date as date, with the time part as 00:00:00:
select trunc(CURRENT_DATE) from dual
You can do this:
select TO_CHAR(CURRENT_DATE,'DD-Mon-YYYY')||' 00:00:00' from dual;
there is also EXTRACT function which can be used like that:
SELECT extract(DAY FROM sysdate)
||'-' ||
extract(MONTH FROM sysdate)
|| '-' || extract(YEAR FROM sysdate)
FROM dual;
result: 4-3-2014
Use This Query...
select (TO_CHAR(TRUNC(CURRENT_DATE),'DD-Mon-YYYY HH24:MI:SS')) from dual

How do I get the current year using SQL on Oracle?

I need to add the current year as a variable in an SQL statement, how can I retrieve the current year using SQL?
i.e.
BETWEEN
TO_DATE('01/01/**currentYear** 00:00:00', 'DD/MM/YYYY HH24:MI:SS')
AND
TO_DATE('31/12/**currentYear** 23:59:59', 'DD/MM/YYYY HH24:MI:SS')
Using to_char:
select to_char(sysdate, 'YYYY') from dual;
In your example you can use something like:
BETWEEN trunc(sysdate, 'YEAR')
AND add_months(trunc(sysdate, 'YEAR'), 12)-1/24/60/60;
The comparison values are exactly what you request:
select trunc(sysdate, 'YEAR') begin_year
, add_months(trunc(sysdate, 'YEAR'), 12)-1/24/60/60 last_second_year
from dual;
BEGIN_YEAR LAST_SECOND_YEAR
----------- ----------------
01/01/2009 31/12/2009
Another option is:
SELECT *
FROM TABLE
WHERE EXTRACT( YEAR FROM date_field) = EXTRACT(YEAR FROM sysdate)
Use extract(datetime) function it's so easy, simple.
It returns year, month, day, minute, second
Example:
select extract(year from sysdate) from dual;
Yet another option would be:
SELECT * FROM mytable
WHERE TRUNC(mydate, 'YEAR') = TRUNC(SYSDATE, 'YEAR');
Since we are doing this one to death - you don't have to specify a year:
select * from demo
where somedate between to_date('01/01 00:00:00', 'DD/MM HH24:MI:SS')
and to_date('31/12 23:59:59', 'DD/MM HH24:MI:SS');
However the accepted answer by FerranB makes more sense if you want to specify all date values that fall within the current year.
Why not use YEAR function?
SELECT * FROM table WHERE YEAR(date_field)=YEAR(SYSDATE);
To display the current system date in oracle-sql
select sysdate from dual;