[英]Oracle SQL Get date from year and week number
我在SUBSTR
表中有年份和周YEAR_WEEKNUMBER
,格式为VERSION_YEAR_WEEKNUMBER
weeknumber 到日期。
理想情况下,日期是星期四,但现在我只想将周数转换为该周和年组合中的任何日期。
示例数据只是“VERSION_YEAR_WEEKNUMBER”,例如 VERSION_2020_10。 意思是,2020 年,一年中的第 10 周 (ISO)。 期望的结果应该是 02-MAR-20 和 08-MAR-20 之间的一个日期
您可以分别提取年份和周数:
substr(your_column, instr(your_column, '_', -1, 2) + 1, 4)
substr(your_column, instr(your_column, '_', -1, 1) + 1)
然后将年份编号转换为 ISO 年份的第一天:
trunc(to_date(substr(your_column, instr(your_column, '_', -1, 2) + 1, 4), 'YYYY'), 'IYYY')
并添加周数 - 1 * 7 天以获得该周的星期一,然后添加 3 作为星期四; 或添加周数 * 7 天以获得下一周的星期一,并为您想要的一周中的星期四减去四:
trunc(to_date(substr(your_column, instr(your_column, '_', -1, 2) + 1, 4), 'YYYY'), 'IYYY')
+ (to_number(substr(your_column, instr(your_column, '_', -1, 1) + 1)) * 7)
- 4
YOUR_COLUMN RESULT
--------------- ----------
VERSION_2020_10 2020-03-05
1.2.3_2021_01 2021-01-07
1_2_3_2020_11 2020-03-12
2020_12 2020-03-19
ABC_2020_52 2020-12-24
DEF_2020_53 2020-12-31
GHI_2021_01 2021-01-07
JKL_2021_52 2021-12-30
MNO_2021_53 2022-01-06
db<>fiddle显示中间步骤,以便您查看发生了什么。
将 ISO 周转换为年份并非易事,因为 ISO 年份可能与实际年份不同。
例如,根据 ISO-8601,20 18 -12-31 是 20 19的第 1 周。
我最终得到了这个 function:
FUNCTION ISOWeek2Date(YEAR INTEGER, WEEK 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 ISOWeek2Date;
但是NEXT_DAY
取决于您的 session 的日期语言,因此@MT0 的解决方案会更好。 逻辑是一样的。
使用@Alex Poole 提出的正则表达式提取年份和星期值
转换为 ISO 周相对简单,因为 1 月 4 日始终是一年中的第一个 ISO 周。 所以:
像这样:
SELECT TRUNC( TO_DATE( SUBSTR( value, 9, 4 )||'01-04', 'YYYY-MM-DD' ), 'IW' )
+ INTERVAL '3' DAY
+ INTERVAL '7' DAY * ( SUBSTR( value, 14 ) - 1 )
AS thursday_of_iso_week
FROM table_name
其中,对于样本数据:
CREATE TABLE table_name ( value ) AS
SELECT 'VERSION_2020_10' FROM DUAL UNION ALL
SELECT 'VERSION_2019_1' FROM DUAL
输出:
| THURSDAY_OF_ISO_WEEK | |:------------------- | | 2020-03-05 00:00:00 | | 2019-01-03 00:00:00 |
如果值没有固定的字符位置,则使用INSTR
查找下划线:
SELECT TRUNC( TO_DATE( SUBSTR( value, INSTR( value, '_' ) + 1, 4 )||'01-04', 'YYYY-MM-DD' ), 'IW' )
+ INTERVAL '3' DAY
+ INTERVAL '7' DAY * ( SUBSTR( value, INSTR( value, '_', -1 ) + 1 ) - 1 )
AS thursday_of_iso_week
FROM table_name
其输出与上述相同。
db<> 在这里摆弄
您可以将以下 CTE 加入到您的查询中
select weekdate, to_char(weekdate, 'IW-yyyy') week_year from (
SELECT LEVEL weeknr, to_date('2020-01-02', 'yyyy-MM-dd') + numtodsinterval((LEVEL-1)*7, 'day') weekdate
FROM dual
CONNECT BY LEVEL <= 53
);
对于联接,请使用 CTE 的 SUBSTR 和 WEEK_YEAR 的结果。 WEEKDATE 将是日期。 此 CTE 生成 2020 年所有星期四的所有周数(1 月 2 日是 2020 年的第一个星期四)。 如果您需要更多日期,只需对“LEVEL”使用另一个限制。 如果您有大量源数据或非常频繁地查询数据,我建议通过在开头附加“create table ... as”并将其放入表中(一次完成)并在 WEEK_YEAR 上创建索引(并生成足够的数据,以便您的解决方案可以长时间工作)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.