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

时间:2015-02-09 10:44:16

标签: sql string oracle date

我在数据库中存储了类似String的日期。 格式为'yyyy-ww'(例如:'2015-43')。

我需要得到一周的第一天。

我尝试将此字符串转换为日期,但函数“to_date”没有“ww”选项。

你有想法进行这次转换吗?

修改

根据答案测试结果 -

感谢您的问题,但是我的解决方案在我的背景下有很多问题:

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

==>错误:ORA-01722:无效数字

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

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

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

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

6 个答案:

答案 0 :(得分:0)

尝试使用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

答案 1 :(得分:0)

  

我在数据库中存储了类似String的日期。

你永远不应该这样做。这是一个糟糕的设计。您应将日期存储为 DATE ,而不是字符串。对于日期操作的各种要求,Oracle提供了所需的 DATE函数和格式模型。在需要时,您可以提取/显示您想要的方式。

  

我需要得到一周的第一天。

TRUNC (dt, 'IW')返回指定日期或之前的星期一。

无论如何,在您的情况下,您的文字为YYYY-WW格式。您可以先提取年份和周数,然后将它们组合在一起,使用 TRUNC 获取日期。

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

所以,上面应该给你那个星期一的星期一。

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>

答案 2 :(得分:0)

根据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;

然而,有一个问题。用于周数的ISO年份可能与实际年份不同。例如,2008年1月1日是2007年ISO第53期。

我认为只有从日期值生成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;

您的日期范围必须大于2010-01-04且不得大于当天。

答案 3 :(得分:0)

然而,与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;

额外的列有助于显示之前和之后的日期。

答案 4 :(得分:0)

我会做以下事情:

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

上述查询的第一件事是获取字符串2015-43的前四位数并将其截断为最接近的年份(如果使用2015转换转换TO_DATE(),则返回当前月份内的日期; SELECT TO_DATE('2015', 'YYYY') FROM dual返回01-FEB-2015;我们需要将此值截断为YEAR才能获得01-JAN-2015)。然后,我将周数减去一次乘以七,并按IW截断整个事件。这会返回01-OCT-2015see SQL Fiddle here)的日期。

答案 5 :(得分:-1)

这就是我使用的:

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