How to get End date of last 12 months in Oracle - oracle

I need a query where i can get last 12 month's end date from the present system date in oracle .
Below is the sample query i am using in Oracle
select
trunc(add_months(sysdate,level-1),'MM') first_day,
last_day(add_months(sysdate,level-1)) last_day
from dual
connect by level<=12;

Try this please:
SELECT TRUNC (ADD_MONTHS (SYSDATE, -(LEVEL - 1)), 'MM') FIRST_DAY,
LAST_DAY (ADD_MONTHS (SYSDATE, -(LEVEL - 1))) LAST_DAY
FROM DUAL
CONNECT BY LEVEL <= 12;

select
trunc(add_months(sysdate-numtoyminterval(1, 'YEAR'),level-1),'MM') first_day,
last_day(add_months(sysdate-numtoyminterval(1, 'YEAR'),level-1)) last_day
from dual
connect by level<=12;
Instead to start now i.e. sysdate, the start will be one year ago: sysdate-numtoyminterval(1, 'YEAR')

Related

Just the month january not working

In this query I found the weeks of month, for example november begin 1th Wednesday and ends sunday 5.
These are the first week on november.
SELECT * FROM (
WITH days AS
(SELECT to_date('01012017','ddmmyyyy') + level-1 date_in
FROM dual
CONNECT BY level < 32)
SELECT date_in,
TO_CHAR(date_in,'IW') - TO_CHAR(TRUNC(date_in,'MM'),'IW') + 1 week_number
FROM days) where week_number = 1;
The week_number can change depending of the weeks of the month, but in January is not working.
Your requirement is not clear for me but perhaps you are looking for this:
SELECT TRUNC (next_day(TRUNC(TO_DATE('20022017','ddmmyyyy'), 'mm'),'monday') - 1), 'IW') AS first_week
FROM dual;
I'm still a bit unclear as to what you're looking for, but perhaps the following query will help you on your way:
WITH YEAR_START AS (SELECT TO_DATE('01012017', 'DDMMYYYY') AS FIRST_DAY_OF_YEAR
FROM DUAL),
MONTH_START AS (SELECT FIRST_DAY_OF_YEAR AS FIRST_DAY_OF_MONTH
FROM YEAR_START
UNION ALL
SELECT ADD_MONTHS(FIRST_DAY_OF_YEAR, LEVEL) AS FIRST_DAY_OF_MONTH
FROM YEAR_START
CONNECT BY LEVEL <= 11),
MONTH_START_AND_END AS (SELECT FIRST_DAY_OF_MONTH,
ADD_MONTHS(FIRST_DAY_OF_MONTH, 1) - INTERVAL '1' DAY AS LAST_DAY_OF_MONTH
FROM MONTH_START),
ABS_MONTH_WEEKS AS (SELECT FIRST_DAY_OF_MONTH,
LAST_DAY_OF_MONTH,
TO_NUMBER(TO_CHAR(FIRST_DAY_OF_MONTH, 'IW')) AS ABS_FIRST_WEEK_OF_MONTH,
TO_NUMBER(TO_CHAR(LAST_DAY_OF_MONTH, 'IW')) AS ABS_LAST_WEEK_OF_MONTH
FROM MONTH_START_AND_END),
REL_MONTH_WEEKS AS (SELECT a.*,
1 AS REL_FIRST_WEEK_OF_MONTH,
ABS_LAST_WEEK_OF_MONTH - CASE
WHEN ABS_FIRST_WEEK_OF_MONTH > ABS_LAST_WEEK_OF_MONTH THEN 0
ELSE ABS_FIRST_WEEK_OF_MONTH-1
END AS REL_LAST_WEEK_OF_MONTH
FROM ABS_MONTH_WEEKS a)
SELECT *
FROM REL_MONTH_WEEKS;
Best of luck.

Extract only the current year in oracle

I need to get the current year from the oracle db. For an example I need to return 2017 as the answer for the current year as a number type. I tried using following way.
select to_Number(sysdate, 'YYYY') from student s
But it not works. So what is the easiest way?
You need to_char instead of to_number
select to_char(sysdate, 'YYYY') from student;
That give a string though. you could apply to_number on it further to convert into number.
select to_number(to_char(sysdate, 'YYYY')) from student;
But there is better method using extract:
select extract(year from sysdate) from student;
Use extract
select extract(year from sysdate)
from dual;
get current year start date:
trunc (sysdate, 'yyyy')
select trunc (sysdate, 'yyyy'),SYSDATE from dual;
get current Month start date:
select trunc (sysdate, 'mm'),SYSDATE from dual;
select records in a month/year:
created_date between trunc (sysdate, 'mm') and sysdate;
created_date between trunc (sysdate, 'yyyy') and sysdate;

Retrieve rows with 0 count from Oracle

I am woking on a query which can give back the count divided by month about the offices that will be closed this summer.
SELECT
qa.tmonth,
COUNT(qa.tmonth) AS qtn
FROM
(
SELECT TO_CHAR(CLOSURE_DATE, 'yyyymm') AS tmonth
FROM Holidays
WHERE CLOSURE_DATE >= TO_DATE('20160501', 'YYYY-MM-DD') AND
CLOSURE_DATE <= TO_DATE('20160901', 'YYYY-MM-DD')
) qa
GROUP BY qa.tmonth;
Since the months: May, June, August and September no office will be closed the output is the following:
TMONTH|QTN
201607|80
But I need a thing like this
TMONTH|QTN
201605|0
201606|0
201607|80
201608|0
201609|0
How could I achieve that?
Thanks to all!
You can try with something like this:
SQL> with holidays(closure_date) as
2 (
3 select date '2016-07-01' from dual union all
4 select date '2016-07-02' from dual union all
5 select date '2016-07-03' from dual union all
6 select date '2016-07-04' from dual union all
7 select date '2016-07-05' from dual
8 )
9 select count(closure_date) as closure_days, to_char(day, 'yyyymm') as month
10 from (
11 select date '2016-05-01' + level -1 as day
12 from dual
13 connect by date '2016-05-01' + level -1 <= date '2016-09-30'
14 ) days
15 left outer join holidays
16 on (day = closure_date)
17 group by to_char(day, 'yyyymm') ;
CLOSURE_DAYS MONTH
------------ ------
0 201608
5 201607
0 201606
0 201605
0 201609
SQL>
This uses a query to build the list of all the days between a starting and an ending date; I used 01/05 and 30/09 and called it days.
Then it queries days with the holidays table in outer join; this way you can count only the days for which there is a corrensponding value in the closure days list, thus counting the closure days for each day, month year; the aggregation for year and month completes the job
A similar approach like above. Tip: You can execute the two sub-queries separately, to analyse the logic.
select to_char (m.month, 'yyyymm') as TMONTH, m.month,
nvl (h.qtn, 0) as QTN
from
(
SELECT add_months(trunc (SYSDATE, 'MONTH'), -(LEVEL-1)) as MONTH
FROM dual
CONNECT BY LEVEL <= 12 -- generate a list of the last 12 month
) m
left join
(
SELECT trunc (closure_date, 'MONTH') as MONTH,
count (*) as QTN
FROM Holidays
group by trunc (closure_date, 'MONTH')
) h
on m.MONTH = h.MONTH
where m.month between DATE '2016-01-01' and sysdate
order by TMONTH desc;

Oracle sysdate flexible date

I worked this statement out
SELECT to_date('30.06.2016', 'dd.mm.yyyy') - (LEVEL-1) DATUM
FROM DUAL
CONNECT BY LEVEL <= 366;
which gives me all dates from 30.06.2016 till 366 days in the past.
So far so good.
What I need to add is that to_date('30.06.2016') is more flexible..
What I mean I always want it to use the last day of June in sysdate + 1 year.
In this case we have 2015 at the moment - so we have 30.06.2016.
If we had 2016 I need it to use 30.06.2017.
If we had 2017 I need it to use 30.06.2018.
..
..
Thanks for your help.
EDIT Solution:
SELECT last_day(add_months(to_date('01.06.' || to_char(sysdate, 'YYYY'), 'dd.mm.yyyy'),12)) - (LEVEL-1) DATUM
FROM DUAL
CONNECT BY LEVEL <= 366
If you want 366 days worth of dates:
SELECT TRUNC( SYSDATE, 'YEAR' ) + INTERVAL '18' MONTH - LEVEL AS DATUM
FROM DUAL
CONNECT BY LEVEL <= 366;
Or if you want a year's worth (365 days or 366 days in a leap year) of dates (1st July this year to 30th June next year):
SELECT TRUNC( SYSDATE, 'YEAR' ) + INTERVAL '18' MONTH - LEVEL AS DATUM
FROM DUAL
CONNECT BY TRUNC( SYSDATE, 'YEAR' ) + INTERVAL '18' MONTH - LEVEL >= TRUNC( SYSDATE, 'YEAR' ) + INTERVAL '6' MONTH;
Is your same code, but get from sysdate the year, using to_char:
select to_date('30.06.'||(to_char(sysdate,'yyyy')+1),'dd.mm.yyyy') from dual;
Here's the steps:
Truncate sysdate to the year, using Trunc().
Add 18 months, using Add_Months().
Subtract one day.

How to get a list of months between 2 given dates using a query?

I have 2 dates, say 28-Mar-2011 and 29-Jun-2011. I need an sql query that will display the months between these 2 dates including the months containing the dates, ie. June, May, April and March.
Something like this
SQL> ed
Wrote file afiedt.buf
select to_char( add_months( start_date, level-1 ), 'fmMonth' )
from (select date '2011-03-30' start_date,
date '2011-06-29' end_date
from dual)
connect by level <= months_between(
trunc(end_date,'MM'),
trunc(start_date,'MM') )
* + 1
SQL> /
TO_CHAR(ADD_MONTHS(START_DATE,LEVEL-
------------------------------------
March
April
May
June
should work.
Gonna add this solution just because I think it's much cleaner than the others:
SELECT ADD_MONTHS(TRUNC(TO_DATE('28-Mar-2011', 'DD-MON-YYYY'), 'MON'), ROWNUM - 1) date_out
FROM DUAL
CONNECT BY ADD_MONTHS(TRUNC(TO_DATE('28-Mar-2011', 'DD-MON-YYYY'), 'MON'), ROWNUM - 1)
<= TRUNC(TO_DATE('29-Jun-2011', 'DD-MON-YYYY'), 'MON')
You can use the function MONTHS_BETWEEN
SELECT MOD( TRUNC( MONTHS_BETWEEN( '2011-07-29', '2011-03-28' ) ), 12 ) as MONTHS
FROM DUAL
Output
MONTHS
----------
4
I needed an answer to this a couple of days ago. I found another solution I liked more:
select to_char(which_month, 'Mon-yyyy') month
from
(
select
add_months(to_date(:start_date,'mm-yyyy'), rownum-1) which_month
from
all_objects
where
rownum <= months_between(to_date(:end_date,'mm-yyyy'), add_months(to_date(:start_date,'mm-yyyy'), -1))
order by
which_month
)
You could of course use any format you want. I 'union'ed and summed over another set so that I'd get the months even when they didn't have results.
SELECT MIN (to_date((TO_CHAR (Actual_Date, 'DD-MM-RRRR')),'dd-mm-rrrr')) F_DATE,
MAX (to_date((TO_CHAR (Actual_Date, 'DD-MM-RRRR')),'dd-mm-rrrr')) T_DATE,
TO_CHAR (Actual_Date, 'MM-RRRR') TRX_MONTH
FROM ( SELECT TRUNC (TO_DATE (:P_FDATE, 'dd-mm-rrrr')) + LEVEL - 1
Actual_Date
FROM (SELECT TRUNC (TO_DATE (:P_FDATE, 'dd-mm-rrrr'), 'MM') - 1
AS dt
FROM DUAL)
CONNECT BY LEVEL <=
( TO_DATE (:P_TDATE, 'dd-mm-rrrr')
- TRUNC (TO_DATE (:P_FDATE, 'dd-mm-rrrr'))
+ 1))
GROUP BY TO_CHAR (Actual_Date, 'MM-RRRR')
ORDER BY 1
declare
v_date_from_first_day date;
v_date_to_last_day date;
v_month_name varchar2(10);
v_month_number number;
v_year_number number;
v_month_diff number;
begin
v_date_to_last_day := to_date('31.12.2018');
v_date_from_first_day := to_date('01.01.2018');
select months_between(v_date_to_last_day,v_date_from_first_day) as diff into v_month_diff from dual;
for i in 1..round(v_month_diff, 2) loop
select
to_char(trunc(add_months(v_date_to_last_day - months_between(v_date_from_first_day, v_date_to_last_day), -i)), 'fmMonth') as month_nm,
to_char(trunc(add_months(v_date_to_last_day - months_between(v_date_from_first_day, v_date_to_last_day), -i)), 'MM') as month_num,
to_char(trunc(add_months(v_date_to_last_day - months_between(v_date_from_first_day, v_date_to_last_day), -i)), 'YYYY') as year_num
into v_month_name, v_month_number, v_year_number
from dual;
dbms_output.put_line(v_month_number || '/' || v_year_number);
dbms_output.put_line(v_month_name || '/' || v_year_number);
end loop;
end;
Output:
12/2018
11/2018
10/2018
9/2018
8/2018
7/2018
6/2018
5/2018
4/2018
3/2018
2/2018
1/2018
Here, month names are in Croatian
Prosinac/2018
Studeni/2018
Listopad/2018
Rujan/2018
Kolovoz/2018
Srpanj/2018
Lipanj/2018
Svibanj/2018
Travanj/2018
Ožujak/2018
Veljača/2018
Siječanj/2018

Resources