我有以下问题。 有一个字符串:
There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235
我只需要显示此字符串中的最后一个日期:2015.06.07
。
我尝试使用regexp_substr
insrt
,但它不起作用。
所以这只是测试,如果我能用这个解决方案解决这个问题,我应该将它用于CLOB查询,其中有多个日期,我只需要最后一个。我知道有regexp_count
,这有助于解决这个问题,但我使用的数据库是Oracle 10g,所以它不会工作。
有人能帮助我吗?
答案 0 :(得分:2)
找到此问题解决方案的关键是颠倒this answer中显示的字符串中的单词。
以下是可能的解决方案:
WITH words AS
(
SELECT regexp_substr(str, '[^[:space:]]+', 1, LEVEL) word,
rownum rn
FROM (SELECT 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 2015.06.08 2015.06.17. 2015.07.01. 12345678999 12125235' str
FROM dual) tab
CONNECT BY LEVEL <= LENGTH(str) - LENGTH(REPLACE(str, ' ')) + 1
)
, words_reversed AS
(
SELECT *
FROM words
ORDER BY rn DESC
)
SELECT regexp_substr(word, '\d{4}\.\d{2}\.\d{2}', 1, 1)
FROM words_reversed
WHERE regexp_like(word, '\d{4}\.\d{2}\.\d{2}')
AND rownum = 1;
答案 1 :(得分:1)
从regexp_substr上的文档中,我立即看到了一个问题:
.
(句点)匹配任何字符。你需要使用反斜杠\.
来逃避它们,以便只匹配一个句号字符。
作为参考,我正在关联this post,这似乎是您使用substr
和instr
所采用的方法。
INSTR(string , substring [, position [, occurrence]])
当position为负数时,INSTR会计算并从字符串末尾向后搜索。 position的默认值为1,这意味着该函数开始在字符串的开头搜索。
这里的问题是你的正则表达式只返回一个值,如here所述,因此在多个日期的情况下,你将为instr
函数提供适当的匹配。
现在,由于这个限制,我建议使用this question中提出的方法,即反转整个字符串(和你的正则表达式,即\d{2}\.\d{2}\.\d{4}
),然后第一个匹配将是'最后一场比赛'。然后,执行另一个字符串反转以获取原始日期格式。
也许这不是最佳解决方案,但它应该有效。
答案 2 :(得分:1)
有三种不同的PL / SQL函数可以帮助您。
INSTR
函数将识别日期字符串中第一个“句点”的出现位置。SUBSTR
使用(1)中的值作为起点TO_DATE
针对特定日期掩码:YYYY.MM.DD
会将结果从(2)转换为Oracle日期时间类型。要在程序代码中使用,标准块适用:
DECLARE
v_position pls_integer;
... other variables
BEGIN
sql code and function calls;
END
Oracle 11g R2架构设置:
CREATE TABLE finddate
(column1 varchar2(11), column2 varchar2(39))
;
INSERT ALL
INTO finddate (column1, column2)
VALUES ('row1', '1234567 242424 2015.06.07. 12125235')
INTO finddate (column1, column2)
VALUES ('string2', '1234567 242424 2015.06.07. 12125235')
SELECT * FROM dual
;
查询1 :
select instr(column2,'.',1) from finddate
where column1 = 'string2'
select substr(column2,(20-4),10) from finddate
select to_date('2015.06.07','YYYY.MM.DD') from finddate
<强> Results 强>:
| TO_DATE('2015.06.07','YYYY.MM.DD') |
|------------------------------------|
| June, 07 2015 00:00:00 |
| June, 07 2015 00:00:00 |
答案 3 :(得分:1)
使用regexp_replace()
的方法可以使用10g,假设行的格式相同:
with tbl(col_string) as
(
select 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235'
from dual
)
select regexp_replace(col_string, '^.*(\d{4}\.\d{2}\.\d{2})\. \d*$', '\1')
from tbl;
正则表达式可以理解为:
^ - Match the start of the line
. - followed by any character
* - followed by 0 or more of the previous character (which is any character)
( - Start a remembered group
\d{4}\.\d{2}\.\d{2} - 4 digits followed by a literal period followed by 2 digits, etc
) - End the first remembered group
\. - followed by a literal period
- followed by a space
\d* - followed by any number of digits
$ - followed by the end of the line
然后,regexp_replace将所有内容替换为第一个记住的组(\ 1)。
基本上将整行描述为正则表达式,围绕您想要返回的内容进行分组。如果它可能是除了数字之外的其他字符,你很可能需要在行尾调整正则表达式,但这应该给你一个想法。
为了论证,这也有效仅在时出现2次日期模式:
with tbl(col_string) as
(
select 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235' from dual
)
select regexp_substr(col_string, '\d{4}\.\d{2}\.\d{2}', 1, 2)
from tbl;
返回第二次出现的模式。我希望上面的regexp_replace能更准确地描述解决方案。