简体   繁体   English

Oracle SQL - 年度财政周

[英]Oracle SQL - Fiscal Week of Year

I want to calculate the Fiscal Week of the Year with the following rules:我想用以下规则计算一年中的财政周:

  • The fiscal year always starts on June/01会计年度始终从 June/01 开始
  • The week always starts on Sunday一周总是从星期日开始
  • Samples are provided for 2019 but ideally it should work for any year提供了 2019 年的样品,但理想情况下它应该适用于任何一年

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我尝试做一些类似 TO_NUMBER(TO_CHAR(TO_DATE(DATE_ID + 1,'DD-Mon-YY'),'IW')) -21 的事情,但在日历年结束时我开始得到否定

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:如果您不喜欢 ISO 约会,其中第 1 周是从星期日开始的那一周,在此期间是一年中的第一天,您可以尝试通过将其移回前一个星期日来抵消它 (TRUNC(..,'D'),然后提前一周,然后加上 7 个月。看看这是否适合你:

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.您对日期格式(“yyyymmdd”与“DD-Mon-YY”)感到困惑,所以我在回答中使用了真实日期 (mydate)。 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.重要的是检查您的日期是否 >= 6 月 1 日。完成此操作后,您可以减去当年的 6 月 1 日或前一年的 6 月 1 日。 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;

Demo: https://dbfiddle.uk/N5pX_5cV演示: https://dbfiddle.uk/N5pX_5cV

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.您可以试试这个 - 提供像 31-MAY-19 这样的日期,让您的日历从 01-JUN-19 开始,并定义您想要的天数。 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.有 5 个月的转变,因为代码是从我的常规日历中获取的,并将一周的开始调整为星期日……每次运行长达 2 年的时间测试正常。 So if you want 6 years you'll have to run this 3 times...所以如果你想要 6 年,你必须运行 3 次......

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: R 结果:

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... ... 2025 年 - 上面评论中提到的部分结果...

... ...
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 
... ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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