2015-05-27 7 views
0

В операторе SELECT можно было бы оценить Substr с использованием CASE? Или что было бы лучшим способом вернуть sub string на основе условия?Oracle SQL: использование CASE в инструкции SELECT с помощью Substr

Я пытаюсь получить имя из столбца описания события таблицы. Строка в столбце описания события форматируется либо как text text (Mike Smith) text text, либо text 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 если есть.

Любая помощь была бы принята с благодарностью.

+0

В образце «Джон Доу» в вашем втором абзаце есть квадратные скобки, которые должны быть там? –

+0

Нет, они должны были обозначать, что может быть или не быть в поле. Я отредактировал свой пост, чтобы сделать это более понятным. – Walter41

ответ

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 | 
+0

Спасибо за помощь! Ваше решение отлично поработало. – Walter41

+0

Если вы Если бы все имена были указаны с фамилией сначала и без запятой после фамилии, и вы хотели бы перевернуть их, чтобы первое имя было перечислено первым? – Walter41

+0

@ Walter41 Добавлено редактирование с два разных решения.Если у вас всегда будет запятая, я буду использовать 'SUBSTR' и' INSTR' (как, вероятно, более эффективную), но если формат запятой является необязательным, то 'REGEXP_REPLACE' может быть лучше. – MT0

1

Вы можете использовать INSTR для поиска последнего ')', но я бы предпочел регулярное выражение.

Это извлекает все между первым «(» и последний «)» и СТИМ удалить скобки (Oracle не поддерживает осмотреться в RegEx):

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

Это вернет «John Doe [(Manager)]» из первой строки примера. То, что он хочет, это просто «Джон Доу» (когда я прочитал вопрос). –

+0

Или он вернет «Джон Доу (менеджер», если квадратные скобки не должны быть там (что непонятно из остальной части вопроса). –

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 
0

Вот несколько иной взгляд на эту проблему. Это регулярное выражение начинается с позиции первого открытого символа + 1 (первая буква имени), а затем возвращает первую группу из этой точки в строке, состоящей из 1 или более символов, которые не являются близким или открытым скобка. 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> 
Смежные вопросы