简体   繁体   中英

How to generate the first day of the week, the last day of the week and week number between two dates in Oracle

I would like to insert in table:

  • the first day of the week starting from Monday.
  • the last day of the week as Sunday.
  • the WEEK number => (1-52 or 1-53) based on the ISO standard.

First i tried to select first day, the last day and week number for specific date and it's works:

WITH ranges AS
(
SELECT to_date('29-10-2012', 'dd-MM-yyyy') AS DATE_TEST FROM DUAL
)
SELECT DATE_TEST "DATE",
TO_CHAR( NEXT_DAY( TRUNC(DATE_TEST) , 'SUNDAY' )) "WEEK END DATE",
TO_CHAR(TO_DATE(DATE_TEST,'DD-MON-YYYY'),'WW')+1 "WEEK NUMBER"
FROM ranges ;

But now i would like to display this data between two dates, but i get result only for the start_date. someone can help please.

after, when all good i will insert all in the table.

Thanks

WITH ranges AS(
   select to_date('29-OCT-2012', 'dd-MM-yyyy') START_DATE, 
       to_date('31-DEC-2016', 'dd-MM-yyyy') END_DATE 
from  dual 
)
SELECT START_DATE "DATE",
TO_CHAR( NEXT_DAY( TRUNC(START_DATE) , 'SUNDAY' )) "WEEK END DATE",
TO_CHAR(TO_DATE(START_DATE,'DD-MON-YYYY'),'WW')+1 "WEEK NUMBER"
FROM ranges ;

Looks like you're looking for a calendar .

Based on your RANGES CTE, there's another - calendar which utilizes hierarchical query to create all dates between start_date and end_date . Once you have all dates, extract values you're interested in.

SQL> with
  2  ranges as
  3    (select to_date('29-OCT-2012', 'dd-MM-yyyy') start_date,
  4            to_date('31-DEC-2016', 'dd-MM-yyyy') end_date
  5     from dual
  6    ),
  7  calendar as
  8    (select start_date + level - 1 as datum
  9     from ranges
 10     connect by level <= end_date - start_date + 1
 11    )
 12  select
 13    min(datum) start_date,
 14    min(next_day(datum, 'sunday')) week_end_date,
 15    to_char(datum, 'ww') week_number
 16  from calendar
 17  group by to_char(datum, 'yyyy'), to_char(datum, 'ww')
 18  order by 1;

START_DATE WEEK_END_D WE
---------- ---------- --
29-10-2012 04-11-2012 44
04-11-2012 11-11-2012 45
11-11-2012 18-11-2012 46
18-11-2012 25-11-2012 47
25-11-2012 02-12-2012 48
<snip>
09-12-2016 11-12-2016 50
16-12-2016 18-12-2016 51
23-12-2016 25-12-2016 52
30-12-2016 01-01-2017 53

222 rows selected.

SQL>

Format WW returns 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, see Datetime Format Elements

In order to get the week number according to ISO-8601 standard use format IW . I would suggest like this:

WITH ranges AS(
    SELECT 
        DATE '2012-10-29' START_DATE,
        DATE '2016-12-31' END_DATE 
    FROM dual 
)
SELECT 
    START_DATE, END_DATE,
    TRUNC(START_DATE + 7*(LEVEL-1), 'IW') AS Week_Start_Date,
    TRUNC(START_DATE + 7*(LEVEL-1), 'IW') + 6 AS Week_End_Date,
    TO_CHAR(TRUNC(START_DATE + 7*(LEVEL-1)), 'IYYY-"W"IW') WEEK_NUMBER
FROM ranges
CONNECT BY START_DATE + 7*(LEVEL-1) <= END_DATE;

Here is a way to make the common table expression return a range of dates.

with ranges (dt) as (
   select to_date('29-OCT-2012', 'dd-MM-yyyy') as dt
   from dual
   
   union all
   select ranges.dt+1
   from ranges
   where ranges.dt < to_date('31-DEC-2016', 'dd-MM-yyyy')
)

Then you can use that to calculate the other values.

SELECT dt "DATE"
, TO_CHAR(NEXT_DAY(TRUNC(dt), 'SUNDAY')) "WEEK END DATE"
, TO_CHAR(TO_DATE(dt,'DD-MON-YYYY'),'WW') + 1 "WEEK NUMBER"
, cast(TO_CHAR(dt, 'WW') as int) + 
  case when cast(TO_CHAR(dt, 'D') as int) < cast(TO_CHAR(trunc(dt, 'year'), 'D') as int) then 1 else 0 end  WeekNumberInYear

FROM ranges ;

If you want to have all of your date calculations done at once, check out an example here: https://dbfiddle.uk/?rdbms=oracle_18&fiddle=35e407af3b5bf711bb7ae53b8cf0e608

How are you?

to help, I tried to do some research, I found these links.

enter link description here

enter link description here

I found:

SELECT ROUND((TRUNC(SYSDATE) - TRUNC(SYSDATE, 'YEAR')) / 7,0) CANTWEEK, NEXT_DAY(SYSDATE, 'SUNDAY') - 7 FIRSTDAY, NEXT_DAY(SYSDATE, 'SUNDAY') - 1 LASTDAY FROM DUAL

and

select to_char(sysdate - to_char(sysdate, 'd') + 2, 'yyyymmdd') first_day_of_week, to_char(sysdate - to_char(sysdate, 'd') + 8, 'yyyymmdd') last_day_of_week from dual

and

select sysdate AS today, TRUNC(next_day(sysdate,'MONDAY')-8) as DOMINGO, TRUNC(next_day(sysdate,'SATURDAY')) as SABADO from dual

I don't have oracle here so I couldn't test it well but it should solve what you need, anything let me know:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM