簡體   English   中英

Oracle SQL - 年度財政周

[英]Oracle SQL - Fiscal Week of Year

我想用以下規則計算一年中的財政周:

  • 會計年度始終從 June/01 開始
  • 一周總是從星期日開始
  • 提供了 2019 年的樣品,但理想情況下它應該適用於任何一年

隨附的屏幕截圖提供了一些正確值的示例

我嘗試做一些類似 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

或者在你的情況下,

SELECT date_id,TO_CHAR(ADD_MONTHS(TO_DATE(date_id,'YYYYMMDD'),+7),'IW') week_of_year
  FROM date_dim

如果您不喜歡 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

您對日期格式(“yyyymmdd”與“DD-Mon-YY”)感到困惑,所以我在回答中使用了真實日期 (mydate)。 將您的字符串或數字轉換為正確的日期,您就在那里:-)

重要的是檢查您的日期是否 >= 6 月 1 日。完成此操作后,您可以減去當年的 6 月 1 日或前一年的 6 月 1 日。 嗯,或多或少:-)

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;

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

更新的答案
您可以試試這個 - 提供像 31-MAY-19 這樣的日期,讓您的日歷從 01-JUN-19 開始,並定義您想要的天數。 有 5 個月的轉變,因為代碼是從我的常規日歷中獲取的,並將一周的開始調整為星期日……每次運行長達 2 年的時間測試正常。 所以如果你想要 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 結果:

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 

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