select Last date of next year in oracle - sql

How to get the last date of next year in oracle sql?

Last date of next year is one day before the first day of the year after next. So you should be able to get it by adding 24 months to the first day of THIS year, and then subtracting one day. Like this:
select sysdate, add_months(trunc(sysdate, 'y'), 24) - 1 as last_day_next_year from dual;
SYSDATE LAST_DAY_NEXT_YEAR
---------- ------------------
2016-08-04 2017-12-31
1 row selected.

Try this:
select add_months(to_date('31-DEC-' || to_char(current_date, 'YYYY')),12) from dual;

Something like...
Select last_day(add_months(sysdate, 12 + (12- to_number(to_char(sysdate, 'mm'))))) from dual;

Related

maximum date less than the quarter date

I have table days table.There is oper_day column:
oper_day
01.01.2021
02.01.2021
03.01.2021
**********
**********
31.12.2022
I want to output the maximum date available in a table that is less than the first date of each quarter for example: quarter_date: 01.10.2022 if 30.09.2022 has in a table I give 30.09.2022 else 29.09.2022 .How can I write query?
One could accomplish this by putting the dates into groups by quarter. Then finding the MAX date for that quarter.
SELECT ADD_MONTHS(TRUNC(td.oper_day, 'Q'), 3) next_quarter_begin
,MAX(td.oper_day) max_date_prev_quarter
FROM table_days td
GROUP BY ADD_MONTHS(TRUNC(td.oper_day, 'Q'), 3)
ORDER BY 1
You appear to be asking how to find the last date in each quarter, if so then GROUP BY the data TRUNCated to the start of the quarter and find the maximum date in each quarter (as it will be the latest date before the start of the next quarter).
If you want to ensure that the values are from quarters before the current quarter then you can add a WHERE filter to ignore values in the current quarter or later.
Like this:
SELECT TO_CHAR(TRUNC(oper_day, 'Q'), 'YYYY-Q') AS quarter,
MAX(oper_day) AS last_oper_day_in_quarter
FROM table_name
WHERE oper_day < TRUNC(SYSDATE, 'Q')
GROUP BY TRUNC(oper_day, 'Q')
Which, for the sample data:
CREATE TABLE table_name (oper_day) AS
SELECT DATE '2022-01-01' + LEVEL - 1
FROM DUAL
CONNECT BY DATE '2022-01-01' + LEVEL - 1 <= SYSDATE;
Outputs:
QUARTER
LAST_OPER_DAY_IN_QUARTER
2022-1
31-MAR-22
2022-2
30-JUN-22
2022-3
30-SEP-22
fiddle

Oracle SQL Get date from year and week number

I have year and week numbers in a SQL table in one column with a format as VERSION_YEAR_WEEKNUMBER
I can use the SUBSTR function to just get the YEAR_WEEKNUMBER, but I then need to convert that to a date and I'm not sure how to convert a weeknumber to a date.
Ideally the date would be a Thursday, but right now I'd just like to convert a weeknumber to any date that's in that week and year combination.
Sample data would just be "VERSION_YEAR_WEEKNUMBER" e.g. VERSION_2020_10. Meaning, 2020, 10th week (ISO) of the year. Desired result should be one date between 02-MAR-20 and 08-MAR-20
You can extract the year and week numbers separately:
substr(your_column, instr(your_column, '_', -1, 2) + 1, 4)
substr(your_column, instr(your_column, '_', -1, 1) + 1)
Then convert the year number to the first day of the ISO year:
trunc(to_date(substr(your_column, instr(your_column, '_', -1, 2) + 1, 4), 'YYYY'), 'IYYY')
and either add the number of weeks - 1 * 7 days to get the Monday of that week, then add 3 for the Thursday; or add the number of weeks * 7 days to get the Monday of the following week and subtract four for the Thursday of the week you want:
trunc(to_date(substr(your_column, instr(your_column, '_', -1, 2) + 1, 4), 'YYYY'), 'IYYY')
+ (to_number(substr(your_column, instr(your_column, '_', -1, 1) + 1)) * 7)
- 4
YOUR_COLUMN RESULT
--------------- ----------
VERSION_2020_10 2020-03-05
1.2.3_2021_01 2021-01-07
1_2_3_2020_11 2020-03-12
2020_12 2020-03-19
ABC_2020_52 2020-12-24
DEF_2020_53 2020-12-31
GHI_2021_01 2021-01-07
JKL_2021_52 2021-12-30
MNO_2021_53 2022-01-06
db<>fiddle showing the intermediate steps so you can see what's happening.
Converting from ISO-Week to year is not trival, because the ISO year may differ from the actual year.
For example 2018-12-31 was Week 1 of 2019 according to ISO-8601.
I ended up with this function:
FUNCTION ISOWeek2Date(YEAR INTEGER, WEEK INTEGER) RETURN DATE DETERMINISTIC IS
res DATE;
BEGIN
IF WEEK > 53 OR WEEK < 1 THEN
RAISE VALUE_ERROR;
END IF;
res := NEXT_DAY(TO_DATE( YEAR || '0104', 'YYYYMMDD' ) - 7, 'MONDAY') + ( WEEK - 1 ) * 7;
IF TO_CHAR(res, 'fmIYYY') = YEAR THEN
RETURN res;
ELSE
RAISE VALUE_ERROR;
END IF;
END ISOWeek2Date;
However NEXT_DAY depends on date language of your session, so the solution by #MT0 would be better. The logic is the same.
Extract year and week values with regular expression as proposed by #Alex Poole
Converting to an ISO week is relatively simple as the 4th of January will always be in the first ISO week of the year. So:
Start with the 4th January of your year;
Truncate it back to Monday to be the start of the ISO week;
Add 3 days and you have Thursday of the first ISO week; and then
Add the number of weeks to take it from the 1st week to the required week.
Like this:
SELECT TRUNC( TO_DATE( SUBSTR( value, 9, 4 )||'01-04', 'YYYY-MM-DD' ), 'IW' )
+ INTERVAL '3' DAY
+ INTERVAL '7' DAY * ( SUBSTR( value, 14 ) - 1 )
AS thursday_of_iso_week
FROM table_name
Which, for the sample data:
CREATE TABLE table_name ( value ) AS
SELECT 'VERSION_2020_10' FROM DUAL UNION ALL
SELECT 'VERSION_2019_1' FROM DUAL
Outputs:
| THURSDAY_OF_ISO_WEEK |
| :------------------- |
| 2020-03-05 00:00:00 |
| 2019-01-03 00:00:00 |
If the values do not have fixed character positions then use INSTR to find the underscores:
SELECT TRUNC( TO_DATE( SUBSTR( value, INSTR( value, '_' ) + 1, 4 )||'01-04', 'YYYY-MM-DD' ), 'IW' )
+ INTERVAL '3' DAY
+ INTERVAL '7' DAY * ( SUBSTR( value, INSTR( value, '_', -1 ) + 1 ) - 1 )
AS thursday_of_iso_week
FROM table_name
Which outputs the same as above.
db<>fiddle here
You could join the following CTE to your query
select weekdate, to_char(weekdate, 'IW-yyyy') week_year from (
SELECT LEVEL weeknr, to_date('2020-01-02', 'yyyy-MM-dd') + numtodsinterval((LEVEL-1)*7, 'day') weekdate
FROM dual
CONNECT BY LEVEL <= 53
);
For the join, use the result of your SUBSTR and WEEK_YEAR of the CTE. WEEKDATE would be the date. This CTE generates all the week numbers for all Thursdays of 2020 (January 2nd was the first Thursday in 2020). If you need more dates, just use another limit for "LEVEL". If you have huge amounts of source data or query the data very frequently, I would recommend to put this in a table (to be done one time) by appending "create table ... as" at the beginning and create an index on WEEK_YEAR (and generating enough data so your solution works for a long time).

Formatting a date in Oracle to show month and day

I have the date as below
SELECT TO_CHAR(SYSDATE, 'DDD') FROM dual;
result for above query is : 117
I need to convert this 117 to month and day. anyone knows how to perform this in PL SQL
the expected result is 04-27
Change 'DDD' to 'MM-DD'.
Try this:
SELECT TO_CHAR(SYSDATE, 'MM-DD')
FROM dual;
OUTPUT:
04-27
Demo:
http://sqlfiddle.com/#!4/622055/7
EDITED:
DDD shows Number of Days from the first of a year.
For Example:
SELECT TO_CHAR(TO_DATE('2018-01-01','YYYY-MM-DD'), 'DDD')
FROM dual;
gives output 001 since it is the First Day of year 2018.
So to break 117 you need the year.
Then you can use this query.
SELECT TO_CHAR(TO_DATE('2018-01-01','YYYY-MM-DD') + column_name - 1, 'MM-DD')
FROM dual;
Example Query:
SELECT TO_CHAR(TO_DATE('2018-01-01','YYYY-MM-DD') + 117 - 1, 'MM-DD')
FROM dual;
OUTPUT:
04-27
Demo:
http://sqlfiddle.com/#!4/622055/37
If you have "117" and want to convert it to a date, you'll have to use a little bit (but really - just a little bit) of arithmetics. As 'DDD' represents number of days since the 1st of current year, add it to ... well the 1st of current year and apply appropriate format mask to convert it to date. I subtracted "1" as you want to get yesterday.
For example:
SQL> select to_char(sysdate, 'ddd') from dual;
TO_
---
117
SQL> select to_date(trunc(sysdate, 'yyyy') + 117, 'dd.mm.rrrr') - 1 resul
2 from dual;
RESULT
----------
27.04.2018
SQL>
Or, using the format you specified (MM-DD):
SQL> select to_char(trunc(sysdate, 'yyyy') + 117 - 1, 'mm-dd') result
2 from dual;
RESUL
-----
04-27
SQL>

first date and last date of month from month and year

How to get first date and last date of month in oracle by giving input parameter as month.
For eg. if i give input month as 'Jan' and Year as '2016' it should give first date and last date of the month.
You can use TRUNC for that:
First day:
TRUNC(your_date, 'MM')
Last day:
ADD_MONTHS(TRUNC(your_date, 'MM'), 1) - 1
You basically TRUNC the month to its first day, add one month to get the first day of the next month, and then go back a day.
If you do not have a date in the month but only the month and the year you can simply use the first of each month to construct a date:
TO_DATE('1.' || your_month || '.' || your_year, 'DD.MM.YYYY')
ADD_MONTHS(TO_DATE('1.' || your_month || '.' || your_year, 'DD.MM.YYYY'), 1) - 1
You can use the TRUNC and LAST_DAY functions for this purpose.
select TRUNC(d,'MM'), LAST_DAY(d)
from (select to_date('01-2016','MM-YYYY') as d from dual);
01-JAN-2016 00:00:00 31-JAN-2016 00:00:00

select records weekly from Oracle table

I need to select recods from oracle table for the current calendar week based on a date datatype field. Currently I am doing like this:
select * from my_table where enter_date > sysdate -7
If today is Thursday, this query will select records seven days from today which infiltrates to last week on Thursday. Is there a way to select records for the current calendar week dynamically?
If your week starts on a Monday then:
select ...
from ...
where dates >= trunc(sysdate,'IW')
For alternative definitions of the first day of the week, trunc(sysdate,'W') truncates to the day of the week with which the current month began, and trunc(sysdate,'WW') truncates to the day of the week with which the current year began.
See other available truncations here: http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions255.htm#i1002084
to_char(sysdate, 'd') returns day of week in [1..7] range; so try using
select *
from my_table
where enter_date >= trunc(sysdate) - to_char(sysdate, 'd') + 1
Here is the SQLFiddel Demo
Below is the query which you can try
select Table1.*
from Table1
where dates > sysdate - TO_CHAR(SYSDATE,'D')