I want to fetch data of last 4 quarter including current quarter.
Suppose if I run the query on 30-MAR-2019 then I want data from 01-APR-2018 to 31-MAR-2019
and if I run the query on 01-apr-2019 then I want data between 01-JUL-2018 and 30-JUN-2019
Could you please help me on the same
The tricky part is getting the last day of the quarter.
This solution calculates the starting day of the range by subtracting 9 months from the target date and then truncating with the 'Q' mask which gives us the first day of the quarter. We then calculate that date again, subtract one day then add twelve months and that gives the last day of the current quarter:
with tgt as ( select date '2019-03-30' as dt from dual
union all select date '2019-02-28' as dt from dual
union all select date '2019-04-01' as dt from dual
)
select trunc(tgt.dt - interval '9' month, 'Q') as range_st,
(trunc(tgt.dt - interval '9' month, 'Q') - 1) + interval '12' month as range_end
from tgt
/
There may be a slicker solution out there, but this is the end of my coffee break :)
this will work:
select TRUNC(sysdate+1, 'Q') - interval '9' month,TRUNC(sysdate+1, 'Q') +
interval '3' month -1
from dual ;
01-JUL-2018 30-JUN-2019
select TRUNC(to_date('30-MAR-2019')+1, 'Q') - interval '9'
month,TRUNC(to_date('30-MAR-2019')+1, 'Q') + interval '3' month -1
from dual ;
01-APR-2018 31-MAR-2019
This is dynamically:
With param as (
Select
to_date(extract(year from add_months(sysdate,-12)) ||
lpad((floor(extract(month from add_months(sysdate,-12))/3)*3)+1,2, '0') || '01',
'yyyymmdd') first_date
from dual
)
Select
level quartal,
Add_months(first_date, ((level-1)*3)) from_dat,
Last_day(add_months(first_date, ((level-1)*3)+3)-1) to_dat
From param
connect by level <= 4;
You can do:
select (trunc(sysdate, 'Q') + interval '3' month) as next_quarter_start,
(trunc(sysdate, 'Q') + interval '15' month) - interval '1' day as next_quarter_end
from dual;
Related
I am trying to write a query that will return the last friday of the previous month This is what I have so far.
SELECT sysdate
FROM DUAL
where (LAST_DAY( SYSDATE ) - INTERVAL '7' DAY,
'Friday' );
Consider:
select next_day(trunc(sysdate, 'month') - interval '8' day, 'Friday') from dual
Rationale:
trunc(sysdate, 'month') gives you the first day of the current month
we offset that value by 8 days so we can the the date 7 days before the end of the previous month
then, next_day() returns the next Friday after this date, that is the last Friday of the month
Try this:
SELECT NEXT_DAY( LAST_DAY( TO_DATE('01-' || TO_CHAR(SYSDATE, 'MON-YYYY')) - 1 ) - INTERVAL '7' DAY, 'FRIDAY' ) FROM DUAL;
I am new to Oracle SQL. I know the LAST_DAY function will return the last day of the month given a specific date. But how can I get the last day of each month in the last two years? Thanks so much!
SELECT TRUNC (ADD_MONTHS (SYSDATE, -(LEVEL - 1)), 'MM') FIRST_DAY,
LAST_DAY (ADD_MONTHS (SYSDATE, -(LEVEL - 1))) LAST_DAY
FROM DUAL
CONNECT BY LEVEL <= 24;
Here you go:
WITH cteTwo_years_ago AS (SELECT TRUNC(SYSDATE - INTERVAL '2' YEAR, 'MONTH') AS TWO_YEARS_AGO
FROM DUAL),
cteMonth_intervals AS (SELECT INTERVAL '1' MONTH * (LEVEL-1) AS SEQ
FROM DUAL
CONNECT BY LEVEL-1 < 24),
cteDates AS (SELECT TWO_YEARS_AGO + SEQ AS MONTH_START
FROM cteTwo_years_ago
CROSS JOIN cteMonth_intervals)
SELECT LAST_DAY(MONTH_START)
FROM cteDates
First and last date of each month in interval from given date up today.
DEFINE start_date=TO_DATE('01.01.2020','DD.MM.YYYY');
SELECT
ADD_MONTHS(&start_date,LEVEL-1) first_day_in_month,
ADD_MONTHS(&start_date,LEVEL)-1 last_day_in_month
FROM DUAL CONNECT BY LEVEL <= FLOOR(MONTHS_BETWEEN(SYSDATE,&start_date));
I got this query on order to get all the days from the first day of the year (01/01/2018) to the end of next year (31/12/2019).
SELECT MYDATE,
TO_CHAR(NR_OF_SUNDAYS + 1,'FM09') WEEK_NUM,
FROM
(
SELECT MYDATE,
( (TRUNC(MYDATE,'DAY') - TRUNC(TRUNC(MYDATE,'YYYY'),'DAY')) / 7 ) +
CASE WHEN TO_CHAR(TRUNC(MYDATE,'YYYY'),'DAY') = 'SUN' THEN 1 ELSE 0 END AS NR_OF_SUNDAYS
FROM
( SELECT TRUNC (SYSDATE, 'YY') - 1 + LEVEL AS MYDATE
FROM DUAL
CONNECT BY LEVEL <= TRUNC (ADD_MONTHS (SYSDATE, 24), 'YY') -
TRUNC (SYSDATE, 'YY')
)
)
I need a column that specifies the following cases:
1) CASE WHEN MYDATE < TO_CHAR(SYSDATE, 'DD/MM/YYYY') THEN 'PAST DUE'
(this works its easy and no problem)
2) if my current =< mydate
week_num then 'CURRENT WEEK'(Excluding PAST DUE)
3) if my current week + one week then
'NEXT WEEK' (Excluding PAST DUE)
4) else FUTURE
Thanks a lot for your help.
So, in my answer I tried retain the logic behind your week number calculation.
However keep in mind that you could calculate week number using oracle to_char(date,'WW'), to_char(date,'IW'), to_char(date,'W') functions and then your life would be easier.
WW Week of year (1-53) where week 1 starts on the first day of the year and continues to the seventh day of the year.
W Week of month (1-5) where week 1 starts on the first day of the month and ends on the seventh.
IW Week of year (1-52 or 1-53) based on the ISO standard.
Having said all that here is my solution that uses only sql (note that defining and using a function would be a lot easier), based on your calculation method.
with date_table as (
SELECT MYDATE, to_number(TO_CHAR(NR_OF_SUNDAYS + 1,'FM09')) WEEK_NUM, to_number(to_char(MYDATE+1,'IW')) as nu
FROM
(
SELECT MYDATE,
( (TRUNC(MYDATE,'DAY') - TRUNC(TRUNC(MYDATE,'YYYY'),'DAY')) / 7 ) +
CASE WHEN TO_CHAR(TRUNC(MYDATE,'YYYY'),'DY', 'NLS_DATE_LANGUAGE = american') = 'SUN' THEN 1 ELSE 0 END AS NR_OF_SUNDAYS
FROM
( SELECT TRUNC (SYSDATE, 'YY') - 1 + LEVEL AS MYDATE
FROM DUAL
CONNECT BY LEVEL <= TRUNC (ADD_MONTHS (SYSDATE, 24), 'YY') -TRUNC (SYSDATE,'YY')
)
)
),
todays_week as
(
select distinct WEEK_NUM from date_table
where trunc(sysdate)=trunc(mydate)
),
pre_final as (
select MYDATE,WEEK_NUM, (select WEEK_NUM from todays_week) as todaysweek from date_table)
select MYDATE,sysdate,WEEK_NUM,todaysweek,
case when trunc(MYDATE) < trunc(sysdate) then 'PAST DUE'
when todaysweek = WEEK_NUM and abs(MYDATE-sysdate)<=7 then 'CURRENT WEEK'
when todaysweek +1 = WEEK_NUM and abs(MYDATE-sysdate)<=14 then 'Next Week'
else 'Future' end as description
from pre_final;
The main idea is to find today's week number and then use case when.
Here is my fiddle link with the results.
http://sqlfiddle.com/#!4/3149e4/148
EDIT 1:
Now, similar results one could achive with something like this:
select res.*,
case when trunc(MYDATE) < trunc(sysdate) then 'PAST DUE'
when todaysweek = WEEK_NUM and abs(MYDATE-sysdate)<=7 then 'CURRENT WEEK'
when todaysweek +1 = WEEK_NUM and abs(MYDATE-sysdate)<=14 then 'Next Week'
else 'Future' end as description
from (
SELECT MYDATE, to_number(to_char(MYDATE,'IW')) as WEEK_NUM,to_number(to_char(sysdate,'IW')) as todaysweek
FROM
( SELECT TRUNC (SYSDATE, 'YY') - 1 + LEVEL AS MYDATE
FROM DUAL
CONNECT BY LEVEL <= TRUNC (ADD_MONTHS (SYSDATE, 24), 'YY') -TRUNC (SYSDATE,'YY')
)) res
I try to get a query without parameters to obtain the list of dates from the current month.
Something like this:
SYSDATE = 16/07/15
I want the next list:
01/07/15
02/07/15
...
30/07/15
31/07/15
Here's what I got to work:
SELECT TRUNC(SYSDATE, 'MM') + LEVEL - 1 AS day
FROM dual
CONNECT BY TRUNC(TRUNC(SYSDATE, 'MM') + LEVEL - 1, 'MM') = TRUNC(SYSDATE, 'MM')
;
The key in this query is TRUNC(SYSDATE, 'MONTH') which is the first day of the current month.
We use hierarchical queries to keep adding one day to the first day of the month until the value is no longer in the current month.
We use LEVEL - 1 because LEVEL starts from 1 and we need it to start from zero.
Here's a pseudo-query for what the above query does:
SELECT (start_of_month + days) AS day
FROM dual
WHILE MONTH_OF(start_of_month + days) = current_month
This query be a bit easier to understand:
SELECT *
FROM
(
SELECT TRUNC(SYSDATE, 'MM') + LEVEL - 1 AS day
FROM dual
CONNECT BY LEVEL <= 32
)
WHERE EXTRACT(MONTH FROM day) = EXTRACT(MONTH FROM SYSDATE)
Selects all the days for current month
SELECT TO_CHAR (TRUNC (SYSDATE, 'MM'), 'YYYYMMDD')+(LEVEL - 1) each_date
FROM DUAL a
CONNECT BY LEVEL < (TO_NUMBER (TO_CHAR (TRUNC (SYSDATE, 'MM') - 1, 'DD'))+1)
This should work:
select trunc(sysdate, 'MONTH') + rownum - 1
from dual
connect by rownum <= to_number(to_char(last_day(sysdate), 'DD'));
This is a trick using connect by. I truncate the date at the month level, effectively setting it to the 1st day of the month, add a day for each "level" and then filter for any day that occurs outside the month.
select day_of_month
from
(select (level - 1) + trunc(to_date('07/16/2015','MM/DD/YYYY'),'MM') day_of_month
from
dual
connect by level <= 31)
where day_of_month < add_months(trunc(to_date('07/16/2015','MM/DD/YYYY'),'MM'),1);
I want to write a query where it displays data between 01-April-2010 to lastday-april-2011.
But I don't want to hard code the year. It should take from system date so it only displays records from this year april to next year april.
Thanks in advance for the help.
select add_months( trunc(sysdate,'YYYY'), -12 )
+ interval '4' month
+ level
- 1
from dual
connect by level <= ( (trunc(sysdate,'YYYY')
+ interval '4' month) -
(add_months( trunc( sysdate, 'YYYY' ), -12 )
+ interval '4' month) )
should work. You could probably simplify the expression that computes the number of rows but I'd have to think for a few minutes about leap years.
If the date column has no time component:
select ...
from mytable
where datecol between add_months(trunc(sysdate,'YYYY'),3)
and add_months(trunc(sysdate,'YYYY'),16)-1
If the date column has a time component:
select ...
from mytable
where datecol >= add_months(trunc(sysdate,'YYYY'),3)
and datecol < add_months(trunc(sysdate,'YYYY'),16)
Your query should be something like this
SELECT *
FROM youtable
WHERE datecolumn BETWEEN to_char(sysdate,'yyyy')+'0401' AND to_char(sysdate,'yyyy')+'0430'