Подстрока от подчеркивания и далее в Oracle - PullRequest
0 голосов
/ 20 июня 2020

У меня есть строка с недостаточной оценкой и некоторыми символами. Мне нужно применить подстроку и получить значения слева, исключая подчеркивание. Поэтому я применил приведенную ниже формулу, и она правильно работает для тех строк, которые имеют подчеркивание (_). Но для строк без (_) он возвращает NULL. Любые предложения, как это можно сделать, в самой подстроке.

Пример: ABC_BASL ---> Работает правильно; AB C ---> дает null

Моя формула, как показано ниже -

select SUBSTR('ABC_BAS',1,INSTR('ABC_BAS','_')-1) from dual;
ABC

select SUBSTR('ABC',1,INSTR('ABC','_')-1) from dual;
(NULL)

Ответы [ 6 ]

4 голосов
/ 20 июня 2020

Вы можете использовать выражение CASE, чтобы сначала проверить наличие подчеркивания:

WITH yourTable AS (
    SELECT 'ABC_BAS' AS col FROM dual UNION ALL
    SELECT 'ABC' FROM dual
)

SELECT
    CASE WHEN col LIKE '%\_%' ESCAPE '\'
         THEN SUBSTR(col, 1, INSTR(col, '_') - 1)
         ELSE col END AS col_out
FROM yourTable;
3 голосов
/ 20 июня 2020

Использовать сопоставление регулярных выражений:

SELECT REGEXP_SUBSTR('ABC_BAS', '(.*)([_]|$)?', 1, 1, NULL, 1) FROM DUAL;

возвращает AB C, а

SELECT REGEXP_SUBSTR('ABC', '(.*)([_]|$)?', 1, 1, NULL, 1) FROM DUAL;

также возвращает AB C.

db <> fiddle here

EDIT

Вышеупомянутое дает правильные результаты, но я пропустил самое простое возможное регулярное выражение для выполнения этой работы:

SELECT REGEXP_SUBSTR('ABC_BAS', '[^_]*') FROM DUAL;

возвращает 'ABC', как и

SELECT REGEXP_SUBSTR('ABC', '[^_]*') FROM DUAL;

db <> здесь скрипт

2 голосов
/ 20 июня 2020

Еще один подход - использовать DECODE в параметре длины substr следующим образом:

substr(str, 
       1, 
       decode(instr(str,'_'), 0, lenght(str), instr(str,'_') - 1)
       )
1 голос
/ 20 июня 2020

Я бы использовал

regexp_replace(text,'_.*')

или, если производительность была проблемой,

substr(text, 1, instr(text||'_', '_') -1)

Например,

with demo(text) as
   ( select column_value
     from   table(sys.dbms_debug_vc2coll('ABC', 'ABC_DEF', 'ABC_DEF_GHI')) )
select text
     , regexp_replace(text,'_.*')
     , substr(text, 1, instr(text||'_', '_') -1)
from   demo;
    
TEXT         REGEXP_REPLACE(TEXT,'_.*') SUBSTR(TEXT,1,INSTR(TEXT||'_','_')-1)
------------ --------------------------- -------------------------------------
ABC          ABC                         ABC
ABC_DEF      ABC                         ABC
ABC_DEF_GHI  ABC                         ABC
1 голос
/ 20 июня 2020

Кажется, вы хотите все до первого '_'. Если это так, в одном из методов используется regexp_replace():

select regexp_replace(str, '(^[^_]+)_.*$', '\1')
from (select 'ABC' as str from dual union all
      select 'ABC_BAS' from dual
     ) s

Более простой метод:

select regexp_substr(str, '^[^_]+')
from (select 'ABC' as str from dual union all
      select 'ABC_BAS' from dual
     ) s

Здесь - скрипт db <>.

0 голосов
/ 20 июня 2020

Хорошо, думаю, я понял. Добавьте nvl в подстроку и вставьте условие, как показано ниже -

select nvl(substr('ABC',1,instr('F4001Z','_')-1),'ABC') from dual;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...