Extract Month in sql and adding 1 - sql

If I add 1 to extract(month from date), then does the result become 13 or 1 (January of next year)
I have the below code:
(extract(day from sysdate) >=1 and extract(month from sysdate)=12) and (targstartdate >= to_date(((extract(month from sysdate))|| '-1-' || (extract(year from sysdate)+1)) , 'mm-dd-yyyy') and targstartdate <= to_date(((extract(month from sysdate)+1)|| '-1-' ||(extract(year from sysdate)+1)) , 'mm-dd-yyyy')

You can use MOD
MOD(extract(month from sysdate)+1,12) + 1

If you are trying to get the month number of the next month, flip your logic. Instead of extracting the month number and adding 1, add one month to the date then extract the month. See the difference below. The second adds one month, then extracts the month of 1 (for January).
select extract( month from to_date('12/15/2017','MM/DD/YYYY')) + 1 from dual
union all
select extract (month from ADD_MONTHS(to_date('12/15/2017','MM/DD/YYYY'),1)) from dual;

Related

Filter last month even in January

The filter below works for most months. However, in January I also want to pull December of the last year.
EXTRACT(MONTH FROM SYSDATE)-1 returns 0
and
EXTRACT(YEAR FROM SYSDATE)
How can I change this filter to make it more dynamic for every month of the year.
WHERE MONTH= EXTRACT(MONTH FROM SYSDATE)-1 AND YEAR = EXTRACT(YEAR FROM SYSDATE)
Even simpler:
WHERE month = TO_NUMBER(TO_CHAR(ADD_MONTHS(SYSDATE,-1),'MM'))
AND year = TO_NUMBER(TO_CHAR(ADD_MONTHS(SYSDATE,-1),'YYYY'))
Subtract a month before using EXTRACT:
WHERE MONTH = EXTRACT(MONTH FROM ADD_MONTHS(SYSDATE, -1))
AND YEAR = EXTRACT(YEAR FROM ADD_MONTHS(SYSDATE, -1))
Something like this, perhaps? ADD_MONTHS will subtract 1 month from sysdate (the result is DATE datatype so you have to apply to_char to it and, possibly, to_number (depending on what the month column contains)). Year, on the other hand, depends on current month - if it is January, take previous year; otherwise, take current year.
where month = to_char(add_months(sysdate, -1), 'mm')
and year = case when extract(month from sysdate) = 1 then extract(year from sysdate) - 1
else extract(year from sysdate)
end

Find Occurence of Day with respect to month Oracle

I want to find the occurrence of a particular day with respect to a month using Oracle RDBMS.
For Example: Like if it is 14-Dec-2020 today. So it is 2nd Monday.
So i want a output as 2. Likewise.
More Examples
7-Dec-2020 --> Output Should Be 1 (As it is first Monday of December)
29-Dec-2020 --> Output Should Be 5 (as it is the 5th Tuesday of December)
You can use a case expression:
select (case when extract(day from sysdate) <= 7 then '1st '
when extract(day from sysdate) <= 14 then '2nd '
when extract(day from sysdate) <= 21 then '3rd '
when extract(day from sysdate) <= 28 then '4th '
else '5th '
end) || to_char(sysdate, 'Day')
from dual;
Here is a db<>fiddle.
In the with clause I build the dates I want (e.g. the whole month of December 2020), and I use row_number analytic function to rank my dates based on YYYYMMD format. I use D not DD, because D means the day of the week. I also use nsl_parameter (nls_date_language) because the starting day is not the same for all countries
Then I convert the rank column (rnb) to date using to_date(lpad(rnb, 2, '0'), 'DD'). I did that as I need to make oracle spell the occurence using this date format 'DDth'.
Then I concatenate the result with "fmDay Month Year" format
with dates as (
select DATE '2020-12-01' + level - 1 dt
, row_number()over (
partition by to_char(DATE '2020-12-01' + level - 1, 'YYYYMMD','nls_date_language = ENGLISH')
order by DATE '2020-12-01' + level - 1) rnb
from dual
connect by level <= 31
)
select dt
, Initcap(to_char(to_date(lpad(rnb, 2, '0'), 'DD'), 'DDth','nls_date_language = ENGLISH'))
||' '||to_char(dt, 'fmDay Month YYYY', 'nls_date_language = ENGLISH') Occurence
from dates
order by dt
;
This is just a little math. The first seven days is the first occurrence for each day, the next seven days is the second occurrrence and so on. So get the day number, e.g. 14, subtract one and apply an integer division then add one again.
select trunc((extract(day from sysdate) - 1) / 7) + 1 from dual;

Find out last month's data when rolling into a new year

Currently, I am using this code to look at the previous month's data for quicksight in Amazon's Athena (this first part works*):
SELECT month, count(1)
FROM table1
WHERE CAST(EXTRACT(month from now()) - 1 as VARCHAR(2)) = month
GROUP BY month
The challenge is how to ensure that this code will work once we roll over into a new year? I currently have
SELECT month, count(1)
FROM table1
WHERE CASE WHEN( month = '1' THEN month = '13'
ELSE month
END)
CAST(EXTRACT(month from now()) - 1 as VARCHAR(2)) = month
GROUP BY month
To clarify, month was input as a string, hence the CAST as VARCHAR(2) to get "01" through "12".
My thought process behind this was that if month = '01', then it reads it as '13', then extracts '1', equaling '12'. But not sure if that will work
You can use the date_add function to subtract one month from today:
SELECT DATE_ADD('month', -1, NOW())
Alternatively you can subtract an interval of one month to achieve the same results:
SELECT NOW() - INTERVAL '1' MONTH
In both cases you can then use MONTH(…) or EXTRACT(MONTH FROM …) to get the month number.
You seem to want:
where month = extract(month from now()) - 1 or
(extract(month from now()) = 1 and month = 12)

Returning a Date Range based on Day of the Month

Select *
From Orders
WHERE (
extract(day from sysdate)<=21
and
to_date(SCHEDULEDATE , 'yyyy/mm/dd') between
to_date((to_char(sysdate, 'YYYY')||'/'||cast((extract(month from sysdate)-1)as char)||'/22'),'yyyy/mm/dd') and to_date((to_char(sysdate,'YYYY')||'/'||cast((extract(month from sysdate))as char)||'/21'),'yyyy/mm/dd')
)
or
(
extract(day from sysdate)>21
and
to_date(SCHEDULEDATE , 'yyyy/mm/dd') between
to_date((to_char(sysdate, 'YYYY')||'/'||cast((extract(month from sysdate))as char)||'/22'),'yyyy/mm/dd') and to_date((to_char(sysdate, 'YYYY')||'/'||cast((extract(month from sysdate)+1)as char)||'/21'),'yyyy/mm/dd')
)
I'm trying to figure out a simple way of returning a set of date ranges based on the day of the Month. If the Day of the month of less than or Equal to I want it to return all orders the have a schedule date between the 22 of the Month before and the 21st of the Current month. If the Day of the month is greater than 21 I would like it return all orders that have a schedule date of the current month up to the end of the month. I've tried to use a case in the where with no luck. What I have now doesn't seem to work either. Any help would be appreciated.
I think this does what you want:
WHERE (extract(day from sysdate) <= 21 and
scheduledate >= add_months(trunc(sysdate, 'MON'), -1) + 21 and
scheduledate < trunc(sysdate, 'MON') + 21
) or
(extract(day from sysdate) > 21 and
trunc(scheduledate, 'MON') = trunc(sysdate, 'MON')
)

Oracle SQL to get first day of month

Requirement is input date should produce first day of the month.
Condtions are:
If the date entered is between 16-nov to 30-nov, then the first day will be 16-nov.
if the date entered is between 1-nov to 15-nov , then the first day will be 01-nov.
for all other month it should return 01st day of corresponding month.
Building on Tim Biegeleisen's solution, simplifying it and avoid the date-to-text-to-date conversions. Note the use of TRUNC to get the first date of the period.
SELECT
CASE
WHEN EXTRACT(MONTH FROM DATE_COL) = 11 AND EXTRACT(DAY FROM DATE_COL) >= 16
THEN TRUNC(DATE_COL, 'MONTH') + 15
ELSE TRUNC(DATE_COL, 'MONTH')
END AS FIRST_OF_MONTH
FROM T1
I used a lengthy CASE expression to handle this, containing the logic for the three cases you mentioned in your question.
SELECT CASE WHEN EXTRACT(month FROM date) = 11 AND
EXTRACT(day FROM date) >= 16
THEN TO_DATE(EXTRACT(year FROM date) || '-11-16', 'yyyy-mm-dd')
ELSE TO_DATE(EXTRACT(year FROM date) || '-' || EXTRACT(month FROM date) ||
'-01', 'yyyy-mm-dd')
END AS newDate
FROM yourTable