2

我有以下问题。有一个字符串:

There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235

我只需要显示此字符串中的最后一个日期:2015.06.07。我试过了regexp_substrinsrt但它不起作用。所以这只是测试,如果我可以用这个解决方案解决这个问题,我应该将它用于有多个日期的 CLOB 查询,我只需要最后一个。我知道有regexp_count,这有助于解决这个问题,但我使用的数据库是 Oracle 10g,所以它不会工作。

有人可以帮助我吗?

4

4 回答 4

3

找到这个问题的解决方案的关键是反转这个答案中出现的字符串中的单词的想法。

这是可能的解决方案:

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;
于 2015-06-28T20:42:15.003 回答
1

regexp_substr的文档中,我立即发现了一个问题:

.句点)匹配任何字符。你需要用反斜杠转义那些:\.为了只匹配一个句点字符。

作为参考,我正在链接这篇文章,这似乎是您使用substrand所采用的方法instr

Oracle 的相关文档

INSTR(string , substring [, position [, occurrence]])

当 position 为负数时,INSTR 从字符串末尾开始计数并向后搜索。position 的默认值为 1,表示函数从字符串的开头开始搜索。

这里的问题是您的正则表达式只返回一个值,如此所述,因此在多个日期的情况下您将为instr函数提供适当的匹配。

现在,由于这个限制,我建议使用在这个问题中提出的方法,即反转整个字符串(以及您的正则表达式 ie \d{2}\.\d{2}\.\d{4}),然后第一个匹配将是“最后一个匹配”。然后,执行另一个字符串反转以获得原始日期格式。

也许这不是最好的解决方案,但它应该工作。

于 2015-06-28T11:59:12.850 回答
1

有三种不同的 PL/SQL 函数可以帮助您实现目标。

  1. INSTR函数将识别日期字符串中第一个“句点”出现的位置。
  2. SUBSTR使用 (1) 中的值作为起点应用于整个字符串
  3. TO_DATE对于特定日期掩码:YYYY.MM.DD将 (2) 中的结果转换为 Oracle 日期时间类型。

为了在程序代码中进行这项工作,标准块适用:

 DECLARE
    v_position pls_integer;
    ... other variables
 BEGIN
    sql code and function calls;

 END

SQL小提琴

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

结果

| TO_DATE('2015.06.07','YYYY.MM.DD') |
|------------------------------------|
|             June, 07 2015 00:00:00 |
|             June, 07 2015 00:00:00 |
于 2015-06-29T12:50:58.877 回答
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 更准确地描述了解决方案。

于 2015-07-01T14:20:59.900 回答