我在数据库中存储了类似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
答案 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-2015
(see 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;