简体   繁体   English

SQL Oracle如何将String Week转换为日期

[英]SQL Oracle How to convert String Week into date

I have dates stored like String in database. 我有像字符串一样存储在数据库中的日期。 The format is 'yyyy-ww' (example: '2015-43'). 格式为“ yyyy-ww”(例如:“ 2015-43”)。

I need to get the first day of the week. 我需要一周的第一天。

I tried to convert this string into date but there is no 'ww' option for the function "to_date". 我试图将此字符串转换为日期,但函数“ to_date”没有“ ww”选项。

Do you have an idea to perform this convertion? 您有执行此转换的想法吗?

EDIT 编辑

Test results based on the answers - 基于答案的测试结果-

Thanks for your anwsers, but I have many problems to apply your solutions to my context: 感谢您的询问,但将您的解决方案应用于我的环境时遇到很多问题:

select
TRUNC ( 2015 + ((43 - 1) * 7), 'IW' )
from dual

==> Error : ORA-01722: invalid number ==>错误:ORA-01722:无效的数字

select
TRUNC(to_date('2015','YYYY')+ to_number('01') *7, 'IW')
from dual

==> 2015-02-02 00:00:00 I waited for a date in january ==> 2015-02-02 00:00:00我在等待一月的日期

select
trunc(to_date(regexp_substr('2015-01', '\d+',1,2), 'YYYY') + regexp_substr('2015-01', '\d+') * 7, 'IW') dt2
from dual

==> 0039-09-14 00:00:00 ==> 0039-09-14 00:00:00

select
regexp_substr('2015-01', '\d+',1,2) as res1,
regexp_substr('2015-01', '\d+') * 7 as res2
from dual

==> res1 = 01 ==> res2 = 14105 ==> res1 = 01 ==> res2 = 14105

try to use by truncate 尝试通过截断使用

with t as (
 select '16-2010' dt from dual
)
--
--
  select dt, 
         trunc(to_date(regexp_substr(dt, '\d+',1,2), 'YYYY') + regexp_substr(dt, '\d+') * 7, 'IW') dt2
 from t

I have dates stored like String in database. 我有像字符串一样存储在数据库中的日期。

You should never do that. 你绝对不应该那样做。 It is a bad design. 这是一个糟糕的设计。 you should store date as DATE and not as a string . 您应该将日期存储为DATE而不是字符串 For all kinds of requirements for date manipulations Oracle provides the required DATE functions and format models . 对于日期操作的各种要求,Oracle提供了必需的DATE函数和格式模型 As and when needed, you could extract/display the way you want. 在需要时,您可以提取/显示所需的方式。

I need to get the first day of the week. 我需要一周的第一天。

TRUNC (dt, 'IW') returns the Monday on or before the given date. TRUNC (dt, 'IW')返回给定日期或之前的星期一。

Anyway, in your case, you have the literal as YYYY-WW format. 无论如何,对于您来说,您的文字是YYYY-WW格式。 You could first extract the year and week number and combine them together to get the date using TRUNC . 您可以先提取年和周数,然后使用TRUNC将它们组合在一起以获取日期。

TRUNC ( year + ((week_number - 1) * 7)
      , 'IW
      )

So, the above should give you the Monday of the week number passed for that year. 因此,以上内容应为您提供当年的星期几。

SQL> WITH DATA AS
  2    ( SELECT '2015-43' str FROM dual
  3    )
  4  SELECT TRUNC(to_date(SUBSTR(str, 1, 4),'YYYY')+ to_number(SUBSTR(str, instr(str, '-',1)+1))*7, 'IW')
  5  FROM DATA
  6  /

TRUNC(TO_
---------
23-NOV-15

SQL>

According ISO the 4th of January is always in week 1, so your query should look like 根据ISO,1月4日总是在第1周,因此您的查询应类似于

Select 
    TRUNC(TO_DATE(REGEXP_SUBSTR(your_column, '^\d{4}')||'-01-04', 'YYYY-MM-DD')
    + 7*(REGEXP_SUBSTR(your_column, '\d$')-1), 'IW') 
from your_table;

However, there is a problem. 但是,有一个问题。 ISO year used for Week number can be different than actual year. 用于周号的ISO年可以与实际年不同。 For example, 1st Jan 2008 was in ISO week number 53 of 2007. 例如,2008年1月1日是2007年的ISO周53。

I think a proper working solution you get only when you generate ISO weeks from date value. 我认为只有当您从日期值生成ISO周时,您才能获得一个正确的工作解决方案。

WITH w AS 
    (SELECT TO_CHAR(DATE '2010-01-04' + LEVEL * INTERVAL '7' DAY, 'IYYY-IW') AS week_number, 
        TRUNC(DATE '2010-01-04' + LEVEL * INTERVAL '7' DAY, 'IW') AS first_day
    FROM dual
    CONNECT BY DATE '2010-01-04' + LEVEL * INTERVAL '7' DAY < SYSDATE)
SELECT your_Column, first_day
FROM w your_table
    JOIN w ON week_number = your_Column;

Your date range must bigger than 2010-01-04 and not bigger than current day. 您的日期范围必须大于2010-01-04并且不能大于当前日期。

Similar to Lalit's, however, I think I've corrected the math (his seemed to be off a bit when I tested .. ) 但是,与Lalit相似,我认为我已经纠正了数学问题(我在测试时似乎有些偏离。)

  with w_data as (
     select sysdate + level +200  d  from dual connect by level <= 10
     ),
     w_weeks as (
        select d, to_char(d,'yyyy-iw') c
          from w_data
     )
  SELECT d, c, trunc(d,'iw'),
         TRUNC(
         to_date(SUBSTR(c, 1, 4)||'0101','yyyymmdd')-8+to_char(to_date(SUBSTR(c, 1, 4)||'0101','yyyymmdd'),'d')
         +to_number(SUBSTR(c, instr(c, '-',1)+1)-1)*7 ,'IW')
    FROM w_weeks;

The extra columns help show the dates before, and after. 额外的列有助于显示之前和之后的日期。

I would do the following: 我将执行以下操作:

WITH d1 AS (
    SELECT '2015-43' AS mydate FROM dual
)
SELECT TRUNC(TRUNC(TO_DATE(REGEXP_SUBSTR(mydate, '^\d{4}'), 'YYYY'), 'YEAR') + (COALESCE(TO_NUMBER(REGEXP_SUBSTR(mydate, '\d+$')), 0)-1) * 7, 'IW')
  FROM d1

The first thing the above query does is get the first four digits of the string 2015-43 and truncates that to the closest year (if you convert convert 2015 using TO_DATE() it returns a date within the current month; that is SELECT TO_DATE('2015', 'YYYY') FROM dual returns 01-FEB-2015 ; we need to truncate this value to the YEAR in order to get 01-JAN-2015 ). 上面查询的第一件事是获取字符串2015-43的前四位数字并将其截断为最接近的年份(如果使用TO_DATE()转换convert 2015它将返回当前月份内的日期;即SELECT TO_DATE('2015', 'YYYY') FROM dual返回01-FEB-2015 ;我们需要将此值截断为YEAR才能获得01-JAN-2015 )。 I then add the number of weeks minus one times seven and truncate the whole thing by IW . 然后,我将周数减去 7乘以1,然后通过IW截断整个过程。 This returns a date of 01-OCT-2015 ( see SQL Fiddle here ). 这将返回日期01-OCT-2015请参见SQL Fiddle此处 )。

This is what I used: 这是我使用的:

select
to_date(substr('2017/01',1,4)||'/'||to_char(to_number(substr('2017/01',6,2)*7)-5),'yyyy/ddd') from dual;

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

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