I want to calculate the Fiscal Week of the Year with the following rules:
A few samples of correct values are provided with the screenshot attached
I tried to do something like TO_NUMBER(TO_CHAR(TO_DATE(DATE_ID + 1,'DD-Mon-YY'),'IW')) -21 but towards the end of the Calendar year I start to get negatives
SELECT
DATE_ID
, WEEK_OF_YEAR
FROM DATE_DIM
WHERE
DATE_ID IN
(
20190601
, 20190602
, 20190915
, 20191228
, 20191229
, 20200101
, 20200601
, 20200606
, 20200607
)
ORDER BY DATE_ID ASC
;
SELECT TO_CHAR(ADD_MONTHS(SYSDATE,+7),'IW')
FROM dual
Or in your case,
SELECT date_id,TO_CHAR(ADD_MONTHS(TO_DATE(date_id,'YYYYMMDD'),+7),'IW') week_of_year
FROM date_dim
If you don't like the ISO dating where week 1 is the week beginning Sunday during which the 1st of the year falls, you can try offsetting it by moving it back to the previous sunday (TRUNC(..,'D'), then advance a week, then add the 7 months. See if this works for you:
SELECT date_id, TO_CHAR(ADD_MONTHS(TRUNC(date_id,'D') + 7,7),'IW') week_of_year
FROM date_dim
You got confused with your date formats ('yyyymmdd' vs. 'DD-Mon-YY'), so I am using a real date (mydate) in my answer. Convert your string or number to a proper date and you are there:-)
The important thing is to check whether your date is >= June 1. Once this is done you can subtract that year's June 1 or the previous year's one. Well, more or less:-)
select
mydate,
to_char(mydate, 'DY') as tag,
trunc
(
case when to_char(mydate, 'mmdd') >= '0601' then
trunc(mydate + 1, 'iw') + 6 - to_date(to_char(mydate, 'yyyy') || '0601', 'yyyymmdd')
else
trunc(mydate + 1, 'iw') + 6 - to_date(to_char(extract(year from mydate) - 1) || '0601', 'yyyymmdd')
end / 7
) + 1 as fiscal_week
from ...
order by mydate;
UPDATED ANSWER
You can try this - provide the date like 31-MAY-19 to start your calendar from 01-JUN-19 and define how many days you want. There is a shift of 5 months as the code was taken from my regular calendar and adjusted the start of week to sunday...Tested OK for periods up to 2 years per run. So if you want 6 years you'll have to run this 3 times...
WITH
base_calendar AS
(
SELECT CurrDate AS Day_ID,
TO_CHAR(CurrDate,'Day') AS Week_Day_Full,
TO_CHAR(CurrDate,'DY') AS Week_Day_Short,
TO_NUMBER(TRIM(leading '0' FROM TO_CHAR(CurrDate,'D'))) AS Day_Num_of_Week,
--
MAX(CASE WHEN To_Char(CurrDate, 'ddmm') = '2902' THEN EXTRACT(YEAR From CurrDate) END) OVER(Order By CurrDate Rows Between Unbounded Preceding And Current Row) AS last_leap_year,
Count(CASE WHEN ( TO_CHAR(CurrDate,'DY') = 'SUN' And
CurrDate Between To_date('01.06.' || To_Char(EXTRACT(YEAR From CurrDate)), 'dd.mm.yyyy') And To_date('31.05.' || To_Char(EXTRACT(YEAR From CurrDate) + 1), 'dd.mm.yyyy') )
OR
( TO_CHAR(CurrDate,'DY') = 'SUN' And
CurrDate Between To_date('01.06.' || To_Char(EXTRACT(YEAR From CurrDate) - 1), 'dd.mm.yyyy') And To_date('31.05.' || To_Char(EXTRACT(YEAR From CurrDate) ), 'dd.mm.yyyy') )
THEN 1
END) OVER(Order By CurrDate Rows Between Unbounded Preceding And Current Row) AS cnt_sundays
FROM
(
SELECT level n,
-- Calendar starts at the day after this date
TO_DATE('31/05/2019','DD/MM/YYYY') + NUMTODSINTERVAL(level,'DAY') CurrDate
FROM dual
-- Change for the number of days to be added to the table.
CONNECT BY level <= 731
)
)
SELECT DISTINCT
day_id,
CASE WHEN (cnt_sundays + 1 ) - ( (EXTRACT(YEAR From Add_Months(Day_id, - 5)) -EXTRACT(YEAR From MIN(Day_id) OVER()) ) * 53) >= 54 THEN 1
WHEN EXTRACT(YEAR From day_id) <> last_leap_year And day_id > = To_Date('01.06.' || To_Char(EXTRACT(YEAR From day_id)), 'dd.mm.yyyy' )
THEN (cnt_sundays + 1) - ( (EXTRACT(YEAR From Add_Months(Day_id, - 5)) -EXTRACT(YEAR From MIN(Day_id) OVER()) ) * 53) + 1
ELSE (cnt_sundays + 1) - ( (EXTRACT(YEAR From Add_Months(Day_id, - 5)) -EXTRACT(YEAR From MIN(Day_id) OVER()) ) * 53)
END week_of_year,
--
week_day_full,
week_day_short,
CASE week_day_short
WHEN 'SUN' THEN 1
WHEN 'MON' THEN 2
WHEN 'TUE' THEN 3
WHEN 'WED' THEN 4
WHEN 'THU' THEN 5
WHEN 'FRI' THEN 6
WHEN 'SAT' THEN 7
END AS day_num_of_week
FROM base_calendar
ORDER BY day_id
R ESULTS:
DAY_ID WEEK_OF_YEAR WEEK_DAY_FULL WEEK_DAY_SHORT DAY_NUM_OF_WEEK
--------- ------------ ------------- -------------- ---------------
01-JUN-19 1 Saturday SAT 7
02-JUN-19 2 Sunday SUN 1
03-JUN-19 2 Monday MON 2
04-JUN-19 2 Tuesday TUE 3
05-JUN-19 2 Wednesday WED 4
... ...
... ...
13-SEP-19 16 Friday FRI 6
14-SEP-19 16 Saturday SAT 7
15-SEP-19 17 Sunday SUN 1
16-SEP-19 17 Monday MON 2
... ...
30-DEC-19 32 Monday MON 2
31-DEC-19 32 Tuesday TUE 3
01-JAN-20 32 Wednesday WED 4
02-JAN-20 32 Thursday THU 5
...
27-FEB-20 40 Thursday THU 5
28-FEB-20 40 Friday FRI 6
29-FEB-20 40 Saturday SAT 7
01-MAR-20 41 Sunday SUN 1
02-MAR-20 41 Monday MON 2
...
29-MAY-20 53 Friday FRI 6
30-MAY-20 53 Saturday SAT 7
31-MAY-20 1 Sunday SUN 1
01-JUN-20 1 Monday MON 2
02-JUN-20 1 Tuesday TUE 3
03-JUN-20 1 Wednesday WED 4
04-JUN-20 1 Thursday THU 5
05-JUN-20 1 Friday FRI 6
06-JUN-20 1 Saturday SAT 7
07-JUN-20 2 Sunday SUN 1
... ...
... ...
22-MAY-21 51 Saturday SAT 7
23-MAY-21 52 Sunday SUN 1
24-MAY-21 52 Monday MON 2
25-MAY-21 52 Tuesday TUE 3
26-MAY-21 52 Wednesday WED 4
27-MAY-21 52 Thursday THU 5
28-MAY-21 52 Friday FRI 6
29-MAY-21 52 Saturday SAT 7
30-MAY-21 53 Sunday SUN 1
31-MAY-21 53 Monday MON 2
731 rows selected
... with year 2025 - part of the result mentioned in comments above...
... ...
29-MAY-25 53 Thursday THU 5
30-MAY-25 53 Friday FRI 6
31-MAY-25 53 Saturday SAT 7
01-JUN-25 1 Sunday SUN 1
02-JUN-25 1 Monday MON 2
03-JUN-25 1 Tuesday TUE 3
04-JUN-25 1 Wednesday WED 4
05-JUN-25 1 Thursday THU 5
06-JUN-25 1 Friday FRI 6
07-JUN-25 1 Saturday SAT 7
08-JUN-25 2 Sunday SUN 1
... ...
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.