Oracle NUMTODSINTERVAL function and interval function - oracle

Can someone please explain what the below is doing?
and effective_DATE < (TRUNC(CURRENT_DATE) - NUMTODSINTERVAL(EXTRACT(DAY FROM TRUNC( CURRENT_DATE)), 'DAY' ) + INTERVAL '1' DAY)
I don't have access to the database so can not run it myself to test.
What I understand is that the NUMTODSINTERVAL converts a number to an INTERVAL DAY TO SECOND literal.
So say if I ran this query today it would check to see if the effective date is less than the 5th of Feb 2019 - 5 days converted to seconds plus 1 day?
So, 5th Feb - 000000005 + 1 = 6th Feb?
Is this correct or am I looking at this wrong?
Also why would developers use this method?

The second argument to NUMTODSINTERVAL specifies the unit. "INTERVAL DAY TO SECOND" is a confusing name - it just means an abstract interval of time, in this case 5 days.
EXTRACT(DAY FROM TRUNC( CURRENT_DATE)) finds the current day of the month (5 today)
NUMTODSINTERVAL(5, 'DAY') creates an INTERVAL of +5 days
So today it's saying, take Feb 5, subtract 5 days (which = Jan 31), then add one day (so Feb 1).
It seems to be trying to find the first day of the month, which would be much simpler as:
and effective_DATE < TRUNC(CURRENT_DATE, 'MM')

Related

How to handle weekday calculation with date operation in Oracle

I need to handle specific scenario in StorProc where I need to do date calculation excluding Sat & Sun. Weekends are holiday I need to handle the data within working days.
I have implemented below code
if (purchase_date = (trunc(sysdate)-2) or purchase_date = (trunc(sysdate)-1)) Then
specific operation
As I have to exclude Sat & Sun by above implementation is giving wrong results obliviously . For example if today is Monday it has to give me back the date of Friday, my implementation is giving me Saturday or Sunday. I need to calculation with dates for weekdays only. Any help would be appreciated.
Thanks
To compare it to the previous week day, you can use:
IF purchase_date = TRUNC(SYSDATE)
- CASE TRUNC(SYSDATE) - TRUNC(SYSDATE, 'IW')
WHEN 0 THEN 3
WHEN 6 THEN 2
ELSE 1
END
THEN
-- Do something
NULL;
END IF;
TRUNC(date_value) - TRUNC(date_value, 'IW') will count the number of days since the start of the ISO week (which is always midnight on Monday).
Note: Do not use TO_CHAR(date_value, 'D') in an international setting as it will give a different result depending on which country you run it in (the week starts on Friday in Bangladesh, Saturday in some Middle-Eastern countries, Sunday in America and Monday in most of Europe).

Oracle sql how to get the date of a week

I have the following query that gets the week of a date:
SELECT pdm.serie, rta.matricula_ant, TO_CHAR (fecha, 'ww') semana,
SUM (rta.kms_acumulados) kms,
COUNT
(DISTINCT (CASE
WHEN v.secuencia BETWEEN rta.sec_origen AND rta.sec_destino
THEN v.cod_inc
ELSE '0'
END
)
)
- 1 numincidencias
FROM (SELECT ms.tren, ms.fecha_origen_tren, ms.secuencia, ri.cod_inc
FROM r_incidencias ri, mer_sitra ms
WHERE ri.cod_serv = ms.tren
AND ri.fecha_origen_tren = ms.fecha_origen_tren
AND ri.cod_tipoin IN (SELECT cod_tipo_iincidencia
FROM v_tipos_incidencias
WHERE grupo = '45')
AND ri.punto_desde = ms.cod_estacion) v,
r_trenes_asignar rta,
r_maquinas rm,
planificador.pl_dh_material pdm
WHERE rta.fecha BETWEEN TO_DATE ('21/09/2018', 'dd/mm/yyyy') AND TO_DATE ('21/09/2018',
'dd/mm/yyyy'
)
AND rta.serie >= 4000
AND rta.matricula_ant IS NOT NULL
AND rm.matricula_maq = rta.matricula_ant
AND rm.cod_serie = pdm.id_material
AND rta.grafico BETWEEN pdm.desde AND pdm.hasta
AND v.tren(+) = rta.tren
AND v.fecha_origen_tren(+) = rta.fecha
GROUP BY pdm.serie, rta.matricula_ant, TO_CHAR (fecha, 'ww')
ORDER BY pdm.serie, rta.matricula_ant, TO_CHAR (fecha, 'ww')
For example week 1
I want to display
week 1 : 1 january - 7 january
How can I get this?
Oracle offers the TRUNC(datestamp, format) function to manipulate dates this way. You may use a variety of format strings to get the first day of a quarter, year, or even the top of the hour.
Given a particular datestamp value, Oracle returns midnight on the first day of the present week with this expression:
TRUNC(datestamp,'DY')
You can add days to a datestamp. Therefore this expression gives you midnight on the last day of the week
TRUNC(datestamp,'DY') + 6
A WHERE-clause selector for all rows in the present week might be this.
WHERE datestamp >= TRUNC(SYSDATE,'DY')
AND datestamp < TRUNC(SYSDATE,'DY') + 7
Notice that the end of the range is just before (<) midnight on the first day of the next week. You need that because you may have datestamps after midnight on the last day of the week. (Beware using BETWEEN for datestamp ranges.)
And,
SELECT TO_CHAR(TRUNC(SYSDATE,'DY'),'YYYY-MM-DD'),
TO_CHAR(TRUNC(SYSDATE,'DY')+6,'YYYY-MM-DD')
FROM DUAL;
displays the first and last dates of the present week in ISO-like format.
Date arithmetic is cool. It's worth your trouble to study the date-arithmetic functions in your DBMS at least once a year.

Change the year of a date to the current year in PL/SQL

I'm currently trying to do a comparison in my select. If the current date is before August 1st of the current year then display august 1st of the last year, otherwise display august 1st of this year. Essentially I'm trying to do:
CASE
WHEN (SYSDATE < 08/01/2015) THEN
08/01/2014
ELSE
08/01/2015
But I am at a loss as to how to get august for the month. So far I have:
TRUNC(SYSDATE, 'MON')
To get /01/ but how would I get it to constantly return august as the month? Would it be better to hardcode in the date and month and dynamically get the year instead? like 01/08/
Try something like this:
1 select sysdate,
2 trunc(sysdate,'YEAR'),
3 add_months(trunc(sysdate,'YEAR'),7),
4 add_months(trunc(sysdate,'YEAR'),7-12)
5* from dual
SQL> /
SYSDATE TRUNC(SYSDA ADD_MONTHS( ADD_MONTHS(
----------- ----------- ----------- -----------
31-jul-2015 01-jan-2015 01-aug-2015 01-aug-2014
SQL>
the columns are:
1) pulling the current sysdate.
2) converting to the first day of the year.
3) adding 7 months to get Aug 1 of current year.
4) -12 months to get Aug 1 of last year.
(that shows you the usage, you can figure out how to plug those suckers into your CASE statement ;) )

Oracle ORA-01839: date not valid for month specified Leap Year

Oracle 11g
here is a quick one hopefully.
Below is part of a script that gets date only from from the next month
first day of next month to last day. But today 29th feb it thrown an error of
ORA-01839: date not valid for month specified
M.MS_DATE between trunc(sysdate + interval '1' month,'MM') and last_day(sysdate + interval '1' month)
Is there a way round this. Many thanks
I have seen this as well and I consider this a bug in Oracle.
The workaround is to use add_months() instead :
between trunc(add_months(sysdate,1),'MM') and last_day(add_months(sysdate,1));
I would probably use add_months() as a_horse_with_no_name suggests, but just as an alternative if you want to use intervals, you can move the point you do the truncation in the first expression, and include the same truncation in the second expression:
select trunc(sysdate, 'MM') + interval '1' month as first_day,
last_day(trunc(sysdate, 'MM') + interval '1' month) as last_day
from dual;
FIRST_DAY LAST_DAY
---------- ----------
2015-02-01 2015-02-28
This works because all months have a first day, so you don't trip over the documented caveat.
When interval calculations return a datetime value, the result must be an actual datetime value or the database returns an error

Oracle BI: Select all records from last week

I need to get all records with a date between Sunday and Saturday last week, inclusive, for whatever date the query is run. For today, April 19th 2011, that would be from April 10th to April 16th.
When I entered the dates manually and converted the filter to SQL, I got the following syntax:
RESOLVED_DATE BETWEEN timestamp '2011-04-10 00:00:00' AND timestamp '2011-04-16 00:00:00'
I'm not even sure this is correct, because it seems to exclude dates on the 16th itself (shouldn't the time be 23:59:59?)
It is possible to determine the dates you want using combinations of next_day and regular date arithmetic. Below code should be pretty close, but it's untested and probably fails on some corner case, but at least you get the general idea :)
where resolved_date >= next_day( trunc(sysdate) - interval '14' day, 'SUN')
and resolved_date < next_day( trunc(sysdate) - interval '7' day, 'SUN')
trunc(sysdate) truncate the date to day; 2011-04-19 23:32:34 becomes 2011-04-19 00:00:00, i.e. removing the time component.
next_day(sysdate, 'SUN') returns the next sunday. If sysdate happens to be a sunday, the next sunday is returned.
Important: The day names have to be in the same language as your session.
The interval thing is just a standard way of adding/subtracting different units of time from a date.
Putting it all together, the logic for the 19th of April 2011 would be:
Truncate sysdate => 2011-04-19 00:00:00
subtract 14 days => 2011-04-05 00:00:00
Find the next sunday => 2011-04-10 00:00:00
...and
Truncate sysdate => 2011-04-19 00:00:00
subtract 7 days => 2011-04-12 00:00:00
Find the next sunday => 2011-04-17 00:00:00
..resulting in the following query:
where resolved_date >= timestamp '2011-04-10 00:00:00'
and resolved_date < timestamp '2011-04-17 00:00:00'
All resolved_dates that happened on or after the first second of the 10:th but before the first second of the 17:th would be included. Note that >= and < isn't equivalent to between.
A note on performance: I would make sure that Oracle correctly estimates the date range to be 7 days, and that the correct join order/method is used. If you expect the query to run for a while, you can afford to calculate the dates in the application and supply them as date litterals instead of computing them on the fly like I did above.
take a look at the to_date function: http://psoug.org/reference/builtin_functions.html

Resources