簡體   English   中英

從 Oracle SQL 上的周和年數字獲取“一周開始”的日期

[英]Getting a date for "start of the week", from week and year numbers on Oracle SQL

我一直在處理一個按周對許多記錄進行分組的查詢。 周數由

to_char(reportdate, 'IW') as "Week",   

之后使用GROUP BY子句。 “周”總是從星期一開始,如果 1 月 1 日不是星期一,則第 1 周將從上一個星期一開始(或者我已經理解了這行代碼)。

因此,如果獲得如下表(對於三個示例行)

Week  Year  Sales  Visits
 32   2017    22     55
 33   2017    30     65
 01   2019    55     103

我想添加一個帶有日期的列,以便它是一周的開始。 我正在考慮使用分組查詢作為子查詢,然后簡單地在后面添加一個列,但我無法完全弄清楚如何將周數和年數映射到這樣的日期。

我試過這條線來獲取日期

trunc(next_day   (trunc(to_date(Yr,'yy'),'yy')  -1,'Mon') + (7*(Wk - 1))    -7)  

但並不是每一行都成立。

任何為我指明正確方向的想法將不勝感激。

ISO-8601 將一年中的第一周計算為該年大部分天數的第一周。 要在該年中擁有大部分天數,那么它必須包含該年內一周中的至少 4 天,並且必須包含 1 月 4 日。

您可以使用它來計算第一個 iso 周的開始時間:

  • TO_DATE( year, 'YYYY' )將給出 1 月 1 日;
  • 然后你可以增加 3 天到 1 月 4 日;
  • 使用TRUNC( date_value, 'IW' )獲取一年中第一個等周的星期一
  • 然后只需添加從第 1 周到第 N 周的正確偏移量。

測試數據

CREATE TABLE test_data ( Week, Year, Sales, Visits ) AS
SELECT '32', 2017, 22,  55 FROM DUAL UNION ALL
SELECT '33', 2017, 30,  65 FROM DUAL UNION ALL
SELECT '01', 2019, 55, 103 FROM DUAL;

查詢

SELECT t.*,
       TRUNC( TO_DATE( year, 'YYYY' ) + 3, 'IW' ) + 7 * ( week - 1 ) AS week_start
FROM   test_data t

輸出

\n周 | 年 | 銷售 | 訪問 |  WEEK_START\n :--- |  ---: |  ----: |  -----: |  :---------\n 32 |  2017 |  22 |  55 |  07-AUG-17 \n 33 |  2017 |  30 |  65 |  17 年 8 月 14 日 \n 01 |  2019 |  55 |  103 |  18 年 12 月 31 日 \n

db<> 在這里擺弄

根據 ISO-8601,第一周是 1 月 4 日的那一周。 我使用此函數從 ISO-Week 獲取日期:

CREATE OR REPLACE FUNCTION ISOWeekDate(WEEK INTEGER, YEAR 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 ISOWeekDate;

請注意,沒有年份的周數是不夠的,因為 ISO-Year 可能與實際年份不同。 請參閱以下示例:

SELECT to_char(DATE '2019-12-31', 'IYYY-"W"IW') from dual;

TO_CHAR(DATE'2019-12-31','IYYY-"W"IW')
--------------------------------------
2020-W01                              


SELECT ISOWeekDate(1, 2019) from dual;

ISOWEEKDATE(1,2019)
----------------------------
2018-12-31 00:00:00         

當然,當您輸入的周/年值可靠時,您可以簡單地使用SELECT NEXT_DAY(TO_DATE( yr|| '0104', 'YYYYMMDD' ) - 7, 'MONDAY') + ( wk - 1 ) * 7 AS week_start

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM