Oracle SQL:在带有Substr的SELECT语句中使用CASE

时间:2015-05-27 21:43:54

标签: sql oracle

SELECT语句中,是否可以使用CASE评估Substr?或者根据条件返回sub string的最佳方法是什么?

我正在尝试从表的事件描述列中检索名称。事件描述列中的字符串格式为text text (Mike Smith) text texttext text (Joe Schmit (Manager)) text text。我想仅返回名称,但是(Manager)之后的某些名称会丢弃我的SELECT声明。

这是我的SELECT声明:

 SELECT *
 FROM (
 SELECT Substr(Substr(eventdes,Instr(eventdes,'(')+1),1,
    Instr(eventdes,')') - Instr(eventdes,'(')-1)
   FROM mytable
      WHERE admintype = 'admin'
    AND entrytime BETWEEN sysdate - (5/(24*60)) AND sysdate
    AND eventdes LIKE '%action taken by%'
     ORDER BY id DESC
     )
 WHERE ROWNUM <=1

如果没有Mike Smith,则返回(Manager)之类的内容,但如果有,则返回Joe Schmit (Manager之类的内容。

非常感谢任何帮助。

4 个答案:

答案 0 :(得分:3)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE MYTABLE ( id, admintype, entrytime, eventdes ) AS
SELECT 1, 'admin', SYSDATE, 'action taken by (John Doe (Manager)) more text' FROM DUAL;

查询1

SELECT *
FROM ( SELECT REGEXP_SUBSTR( eventdes, '\((.*?)(\s*\(.*?\))?\)', 1, 1, 'i', 1 )
       FROM   mytable
       WHERE  admintype = 'admin'
       AND    entrytime BETWEEN sysdate - (5/(24*60)) AND sysdate
       AND    eventdes LIKE '%action taken by%'
       ORDER BY id DESC
     )
WHERE ROWNUM <=1

<强> Results

| REGEXP_SUBSTR(EVENTDES,'\((.*?)(\S*\(.*?\))?\)',1,1,'I',1) |
|------------------------------------------------------------|
|                                                   John Doe |

修改

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE MYTABLE ( id, admintype, entrytime, eventdes ) AS
SELECT 1, 'admin', SYSDATE, 'action taken by (Doe, John (Manager)) more text' FROM DUAL;

查询1

SELECT SUBSTR( Name, INSTR( Name, ',' ) + 1 ) || ' ' || SUBSTR( Name, 1, INSTR( Name, ',' ) - 1 ) AS Full_Name,
       REGEXP_REPLACE( Name, '^(.*?),\s*(.*)$', '\2 \1' ) AS Full_Name2
FROM ( SELECT REGEXP_SUBSTR( eventdes, '\((.*?)(\s*\(.*?\))?\)', 1, 1, 'i', 1 ) AS Name
       FROM   mytable
       WHERE  admintype = 'admin'
--       AND    entrytime BETWEEN sysdate - (5/(24*60)) AND sysdate
       AND    eventdes LIKE '%action taken by%'
       ORDER BY id DESC
     )
WHERE ROWNUM <=1

<强> Results

| FULL_NAME | FULL_NAME2 |
|-----------|------------|
|  John Doe |   John Doe |

答案 1 :(得分:1)

您可以使用INSTR搜索最后一个')',但我更喜欢正则表达式。

这将提取第一个'('和最后一个')之间的所有内容,并且TRIM删除括号(Oracle不支持在RegEx中查看):

RTRIM(LTRIM(REGEXP_SUBSTR(eventdes, '\(.*\)'), '('), ')')

答案 2 :(得分:0)

可能有一个正则表达式会在没有替换的情况下执行此操作,但我不够聪明,因此我将REGEXP_SUBSTRING替换为多个instr方法并使用REGEXP_REPLACE来替换'(MANAGER)'部分。存在。

SELECT *
FROM (
    SELECT REGEXP_REPLACE(
        REGEXP_SUBSTR(eventdes, '\((.*)\)', 1, 1, 'i', 1), ' \(MANAGER\)', '')
    FROM mytable
    WHERE admintype = 'admin'
    AND entrytime BETWEEN sysdate - (5/(24*60)) AND sysdate
    AND eventdes LIKE '%action taken by%'
    ORDER BY id DESC
 )
WHERE ROWNUM <=1

答案 3 :(得分:0)

这个问题略有不同。此正则表达式从第一个打开的paren + 1(名称的第一个字母)的位置开始,然后返回字符串中该点的第一个组,该组由1个或多个不是紧密的paren或open的字符组成括号。如果有经理,TRIM会删除尾随空格。

SQL> with tbl(id, admintype, entrytime, eventdes ) AS
  2  ( SELECT 1, 'admin', SYSDATE, 'action taken by (John Doe (Manager)) more text' FROM DUAL
  3    union
  4    SELECT 1, 'admin', SYSDATE, 'action taken by (Jane Doe) more text' FROM DUAL
  5  )
  6  select trim(regexp_substr(eventdes, '([^\)\(]+)', instr(eventdes, '(')+1, 1)) name
  7  from tbl;

NAME
----------------------------------------------
Jane Doe
John Doe

SQL>