Як вибрати підстроку в Oracle SQL до певного символу?


82

Скажімо, у мене є стовпець таблиці, який має такі результати:

ABC_blahblahblah
DEFGH_moreblahblahblah
IJKLMNOP_moremoremoremore

Я хотів би мати можливість написати запит, який вибирає цей стовпець із зазначеної таблиці, але повертає лише підстроку до символу Підкреслення (_). Наприклад:

ABC
DEFGH
IJKLMNOP

Функція SUBSTRING, здається, не відповідає завданням, оскільки вона заснована на положенні, а положення підкреслення різне.

Я думав про функцію TRIM (особливо функцію RTRIM):

SELECT RTRIM('listofchars' FROM somecolumn) 
FROM sometable

Але я не впевнений, як би я змусив це працювати, оскільки, здається, це видаляє лише певний список / набір символів, і я справді лише після символів, що ведуть до символу Підкреслення.

Відповіді:


141

Використання комбінації SUBSTR, INSTR та NVL (для рядків без підкреслення) поверне те, що ви хочете:

SELECT NVL(SUBSTR('ABC_blah', 0, INSTR('ABC_blah', '_')-1), 'ABC_blah') AS output
  FROM DUAL

Результат:

output
------
ABC

Використання:

SELECT NVL(SUBSTR(t.column, 0, INSTR(t.column, '_')-1), t.column) AS output
  FROM YOUR_TABLE t

Довідково:

Додаток

Якщо ви використовуєте Oracle10g +, ви можете використовувати регулярний вираз через REGEXP_SUBSTR .


Дякую. Дуже елегантно! (приємно знати і про REGEXP_SUBSTR.) Я навіть не думав шукати підтримку Regex в Oracle.
Крендель

В Oracle ви можете створювати функції (окремі або в пакеті) і використовувати їх у операторі select.
барт

9
Не вдається виконати зі значеннями, які НЕ містять підрядка, який ви шукаєте. instrповертає 0, якщо у вас є INSTR('ABC/D', '_'). Врешті-решт, у вас є підрядок від 0 до (0-1), який є нульовим. Не добре.
Marcel Stör

41

Це можна зробити за допомогою REGEXP_SUBSTR легко.

Будь ласка, використовуйте

REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1) 

де STRING_EXAMPLE - це ваш рядок.

Спробуйте:

SELECT 
REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1) 
from dual

Це вирішить вашу проблему.


1
Я підтримую це рішення, вибране OP, оскільки воно робить трюк. Проте варто зазначити, що це рішення набагато повільніше, ніж рішення @OMG Ponies, особливо якщо воно використовується в будь-яких умовах. Мої тести показали приблизно в 6 разів повільніше виконання однакових запитів. Це питання йде ще далі на тему stackoverflow.com/questions/41156391/…
Істер

Під час мого тестування INSTRрішення працює майже однаково швидко, як REGEXPрішення.
alexherm

7

Вам потрібно отримати позицію першого підкреслення (за допомогою INSTR), а потім дістати частину рядка від 1-го символу до (pos-1), використовуючи substr.

  1  select 'ABC_blahblahblah' test_string,
  2         instr('ABC_blahblahblah','_',1,1) position_underscore,
  3         substr('ABC_blahblahblah',1,instr('ABC_blahblahblah','_',1,1)-1) result
  4*   from dual
SQL> /

TEST_STRING      POSITION_UNDERSCORE RES
---------------- ------------------  ---
ABC_blahblahblah                  4  ABC

Документація Instr

Документація Susbtr


6
SELECT REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1)  from dual

- правильна відповідь, яку опублікував користувач1717270

Якщо ви використовуєте INSTR, це дасть вам позицію для рядка, який передбачає, що він містить "_". Що, якщо цього не стане? Ну, відповідь буде 0. Тому, коли ви хочете надрукувати рядок, він надрукує a NULL. Приклад: Якщо ви хочете видалити домен із "host.domain". У деяких випадках у вас буде лише коротка назва, тобто "хост". Швидше за все, ви хотіли б надрукувати "хост". Ну, з INSTRцим ви отримаєте, NULLтому що не знайшли жодного ".", Тобто надрукуєте від 0 до 0. З цим REGEXP_SUBSTRви отримаєте правильну відповідь у всіх випадках:

SELECT REGEXP_SUBSTR('HOST.DOMAIN','[^.]+',1,1)  from dual;

ВЕДУЧИЙ

і

SELECT REGEXP_SUBSTR('HOST','[^.]+',1,1)  from dual;

ВЕДУЧИЙ



0

Запам’ятайте це, якщо всі ваші рядки в стовпці не мають підкреслення (... або, якщо вихідним буде значення null):

SELECT COALESCE
(SUBSTR("STRING_COLUMN" , 0, INSTR("STRING_COLUMN", '_')-1), 
"STRING_COLUMN") 
AS OUTPUT FROM DUAL

0

Щоб знайти будь-який підрядок із великого рядка:

string_value:=('This is String,Please search string 'Ple');

Потім , щоб знайти рядок 'Ple'з String_valueми можемо зробити , як:

select substr(string_value,instr(string_value,'Ple'),length('Ple')) from dual;

Ви знайдете результат: Ple


0

Якщо позиція рядка не є фіксованою, тоді за допомогою інструкції Select ми можемо отримати очікуваний результат.

Структура таблиці Ідентифікатор VARCHAR2 (100 байт) КЛІЄНТ VARCHAR2 (4000 байт)


Дані - ІДЕНТ. КЛІЄНТА 1001 {"clientId": "con-bjp", "clientName": "ABC", "providerId": "SBS"}
1002 {"IdType": "AccountNo", "Id": "XXXXXXXX3521", "ToPricingId": "XXXXXXXX3521", "clientId": "Test-Cust", "clientName": "MFX"}

Вимога - Знайдіть рядок "ClientId" у стовпці CLIENT і поверніть відповідне значення. Як із "clientId": "con-bjp" -> con-bjp (очікуваний результат)

виберіть CLIENT, substr (substr (CLIENT, instr (CLIENT, '"clientId": "') + length ('" clientId ":"')), 1, instr (substr (CLIENT, instr (CLIENT, '"clientId") : "') + length ('" clientId ":" ')),' "', 1) -1) cut_str з TEST_SC;

КЛІЄНТ cut_str ------------------------------------------------ ----------- ---------- {"clientId": "con-bjp", "clientName": "ABC", "providerId": "SBS"} con- bjp {"IdType": "AccountNo", "Id": "XXXXXXXX3521", "ToPricingId": "XXXXXXXX3521", "clientId": "Test-Cust", "clientName": "MFX"} Test-Cust

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.