Calculate the week ending date in oracle using Saturday as the week end date - oracle

Given a field in Oracle that contains dates, how would you calculate what the week ending date is using Sun thru Sat as your week. For example, if the date is 1/26/2015 (which is a Monday), the query should return 1/31/2015 (which is a Saturday. If the date is 1/31/2015, then the query should return 1/31/2015.

Given any particular date / time value, this expression will return midnight of the preceding Sunday.
TRUNC(whatever_time,'DAY')
So, you can do stuff like this:
SELECT TRUNC(whatever_time,'DAY') week_starting,
TRUNC(whatever_time,'DAY') + 6 week_ending,
SUM(sales)
FROM table
GROUP BY TRUNC(whatever_time,'DAY')
and you'll get what you need.
Notice that TRUNC(whatever_time,'DAY') honors the Oracle session initialization parameter called “NLS_TERRITORY”. For example, in Europe Monday is considered the first business day of the week. Try this.
ALTER SESSION SET NLS_TERRITORY=GERMANY;
SELECT TRUNC( DATE '2013-12-31', 'DAY'),
TRUNC( DATE '2014-01-03', 'DAY')
FROM DUAL;
A complete writeup of this is here: http://www.plumislandmedia.net/sql-time-processing/using-sql-report-time-intervals-oracle/

Related

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.

How to add a day with a specific date using add_months function

I am trying to add a day with a specific date using add_months in oracle database.
I wrote this line:
SELECT ADD_MONTHS('01-JAN-2018', MONTHS_BETWEEN('02-JAN-2018', '01-JAN-2018')) FROM DUAL;
this returns:
01-JAN-18
Why doesn't it return 02-JAN-18?? Can I add one day to the date using this function?
Why doesn't it return 02-JAN-18??
According to MONTHS_BETWEEN documentation,
The MONTHS_BETWEEN function calculates the number of months between
two dates. When the two dates have the same day component or are both
the last day of the month, then the return value is a whole number.
Otherwise, the return value includes a fraction that considers the
difference in the days based on a 31-day month
So,
select MONTHS_BETWEEN('02-JAN-2018', '01-JAN-2018') FROM DUAL ;
yields
.0322580645161290322580645161290322580645
ADD_MONTHS returns the date date plus integer months.
So, .0322.. is considered as integer 0 and your query is equivalent to
SELECT ADD_MONTHS('01-JAN-2018', 0) FROM DUAL;
In order to add 1 months, simply take the difference of two dates.
SELECT ADD_MONTHS(DATE '2018-01-01', DATE '2018-01-02' - DATE '2018-01-01') FROM DUAL;
Or better, add an INTERVAL of 1 month
SELECT DATE '2018-01-01' + INTERVAL '1' MONTH FROM DUAL;
To answer your question, add 1 day, simply use
SELECT DATE '2018-01-01' + 1 FROM DUAL;

Oracle DB to_date with year - to_date(2017,'YYYY') unexpected return

While writing few queries I needed to return only those rows that have date column set in this year (2017) , that's not my problem I know how to write this query in couple of diffrent ways, but I came across something strange and unexpected for me. Can anyone explain why Oracle db 11.2 is behaving this way?
select sysdate from dual
returns:
2017/12/05 09:22:27
select to_date(2017,'YYYY'),trunc(sysdate,'YYYY') from dual
returns :
2017/12/01 00:00:00 2017/01/01 00:00:00
select to_date(2017,'YYYY'),trunc(sysdate,'YYYY') from dual
where trunc(sysdate,'YYYY') = to_date(2017,'YYYY')
no rows returned
Why does to_date(2017,'YYYY') returns 2017/12/01, will it return 2017/01/01 next month? Why does it work that way? I would expect it to always return 2017/01/01 no matter the current month (if month part is indeed changing depending on sysdate).
In Oracle, TO_DATE will assume that:
If you do not specify the year then it is the current year;
If you do not specify the month then it is the current month;
If you do not specify the day then it is the first day of the month;
If you do not specify the hours then it is the midnight hour (0);
If you do not specify the minutes then it is 0 minutes past the hour; and
If you do not specify the seconds then it is 0 seconds into the minute.
You are specifying only the year (2017) so it will be:
Zero minutes and seconds past midnight of the first day of the current month of the year you specify (2017).
If you want the first day of the year then specify the month (and preferably the rest of the date):
select to_date( '201701','YYYYMM'),
trunc(sysdate,'YYYY')
from dual
where trunc(sysdate,'YYYY') = to_date( '201701','YYYYMM' )
Or use a date literal:
select DATE '2017-01-01',
trunc(sysdate,'YYYY')
from dual
where trunc(sysdate,'YYYY') = DATE '2017-01-01'

extract week number from date postgres

I would like to extract the week number as:
2015-52
from a date formatted as:
2015-12-27
How can I perform this in postgres?
my weeks are calculated from monday to sunday.
To get the year and the week in a single character value, use to_char()
select to_char(current_date, 'IYYY-IW');
IW returns the year and the week number as defined in the ISO standard and IYYY returns the corresponding year (which might be the previous year).
If you need the year and the week number as numbers, use extract
select extract('isoyear' from current_date) as year,
extract('week' from current_date) as week;
I have done like this
extract(week from cast(current_date as date))
extract(year from cast(current_date as date))
As same with #a_horse_with_no_name, but be careful there is a little difference between extract('isoyear' from current_date) and extract('year' from current_date) if current_date is within week0 in new year(the last week(53) of last year), especially when you extract week as well.
For example:
The follow output is 2020 not 2021
select EXTRACT('isoyear' from to_timestamp('2021-01-02 17:37:27', 'YYYY-MM-DD hh24:mn:ss')) as year
The follow output is 2021
select EXTRACT('year' from to_timestamp('2021-01-02 17:37:27', 'YYYY-MM-DD hh24:mn:ss')) as year

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