[英]Oracle SQL Get date from year and week number
I have year and week numbers in a SQL table in one column with a format as VERSION_YEAR_WEEKNUMBER
I can use the SUBSTR
function to just get the YEAR_WEEKNUMBER
, but I then need to convert that to a date and I'm not sure how to convert a weeknumber to a date.我在
SUBSTR
表中有年份和周YEAR_WEEKNUMBER
,格式为VERSION_YEAR_WEEKNUMBER
weeknumber 到日期。
Ideally the date would be a Thursday, but right now I'd just like to convert a weeknumber to any date that's in that week and year combination.理想情况下,日期是星期四,但现在我只想将周数转换为该周和年组合中的任何日期。
Sample data would just be "VERSION_YEAR_WEEKNUMBER" eg VERSION_2020_10.示例数据只是“VERSION_YEAR_WEEKNUMBER”,例如 VERSION_2020_10。 Meaning, 2020, 10th week (ISO) of the year.
意思是,2020 年,一年中的第 10 周 (ISO)。 Desired result should be one date between 02-MAR-20 and 08-MAR-20
期望的结果应该是 02-MAR-20 和 08-MAR-20 之间的一个日期
You can extract the year and week numbers separately:您可以分别提取年份和周数:
substr(your_column, instr(your_column, '_', -1, 2) + 1, 4)
substr(your_column, instr(your_column, '_', -1, 1) + 1)
Then convert the year number to the first day of the ISO year:然后将年份编号转换为 ISO 年份的第一天:
trunc(to_date(substr(your_column, instr(your_column, '_', -1, 2) + 1, 4), 'YYYY'), 'IYYY')
and either add the number of weeks - 1 * 7 days to get the Monday of that week, then add 3 for the Thursday;并添加周数 - 1 * 7 天以获得该周的星期一,然后添加 3 作为星期四; or add the number of weeks * 7 days to get the Monday of the following week and subtract four for the Thursday of the week you want:
或添加周数 * 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 showing the intermediate steps so you can see what's happening. db<>fiddle显示中间步骤,以便您查看发生了什么。
Converting from ISO-Week to year is not trival, because the ISO year may differ from the actual year.将 ISO 周转换为年份并非易事,因为 ISO 年份可能与实际年份不同。
For example 20 18 -12-31 was Week 1 of 20 19 according to ISO-8601.例如,根据 ISO-8601,20 18 -12-31 是 20 19的第 1 周。
I ended up with this function:我最终得到了这个 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;
However NEXT_DAY
depends on date language of your session, so the solution by @MT0 would be better.但是
NEXT_DAY
取决于您的 session 的日期语言,因此@MT0 的解决方案会更好。 The logic is the same.逻辑是一样的。
Extract year and week values with regular expression as proposed by @Alex Poole使用@Alex Poole 提出的正则表达式提取年份和星期值
Converting to an ISO week is relatively simple as the 4th of January will always be in the first ISO week of the year.转换为 ISO 周相对简单,因为 1 月 4 日始终是一年中的第一个 ISO 周。 So:
所以:
Like this:像这样:
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
Which, for the sample data:其中,对于样本数据:
CREATE TABLE table_name ( value ) AS
SELECT 'VERSION_2020_10' FROM DUAL UNION ALL
SELECT 'VERSION_2019_1' FROM DUAL
Outputs:输出:
|| THURSDAY_OF_ISO_WEEK |
THURSDAY_OF_ISO_WEEK | |:------------------- |
|:------------------- | |
| 2020-03-05 00:00:00 |
2020-03-05 00:00:00 | |
| 2019-01-03 00:00:00 |
2019-01-03 00:00:00 |
If the values do not have fixed character positions then use INSTR
to find the underscores:如果值没有固定的字符位置,则使用
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
Which outputs the same as above.其输出与上述相同。
You could join the following CTE to your query您可以将以下 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
);
For the join, use the result of your SUBSTR and WEEK_YEAR of the CTE.对于联接,请使用 CTE 的 SUBSTR 和 WEEK_YEAR 的结果。 WEEKDATE would be the date.
WEEKDATE 将是日期。 This CTE generates all the week numbers for all Thursdays of 2020 (January 2nd was the first Thursday in 2020).
此 CTE 生成 2020 年所有星期四的所有周数(1 月 2 日是 2020 年的第一个星期四)。 If you need more dates, just use another limit for "LEVEL".
如果您需要更多日期,只需对“LEVEL”使用另一个限制。 If you have huge amounts of source data or query the data very frequently, I would recommend to put this in a table (to be done one time) by appending "create table... as" at the beginning and create an index on WEEK_YEAR (and generating enough data so your solution works for a long time).
如果您有大量源数据或非常频繁地查询数据,我建议通过在开头附加“create table ... as”并将其放入表中(一次完成)并在 WEEK_YEAR 上创建索引(并生成足够的数据,以便您的解决方案可以长时间工作)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.