Jak wybrać podciąg w Oracle SQL do określonego znaku?

82

Powiedzmy, że mam kolumnę tabeli, która ma wyniki takie jak:

ABC_blahblahblah
DEFGH_moreblahblahblah
IJKLMNOP_moremoremoremore

Chciałbym móc napisać zapytanie, które wybiera tę kolumnę ze wspomnianej tabeli, ale zwraca tylko podciąg do znaku podkreślenia (_). Na przykład:

ABC
DEFGH
IJKLMNOP

Funkcja SUBSTRING wydaje się nie nadawać się do tego zadania, ponieważ jest oparta na pozycji, a pozycja podkreślenia jest różna.

Myślałem o funkcji TRIM (konkretnie o funkcji RTRIM):

SELECT RTRIM('listofchars' FROM somecolumn) 
FROM sometable

Ale nie jestem pewien, jak bym to działał, ponieważ wydaje się, że usuwa tylko pewną listę / zestaw znaków, a tak naprawdę jestem tylko po postaciach prowadzących do postaci Underscore.

Precel
źródło

Odpowiedzi:

141

Użycie kombinacji SUBSTR, INSTR i NVL (dla łańcuchów bez podkreślenia) zwróci to, czego potrzebujesz:

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

Wynik:

output
------
ABC

Posługiwać się:

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

Odniesienie:

Uzupełnienie

Jeśli używasz Oracle10g +, możesz użyć wyrażenia regularnego za pośrednictwem REGEXP_SUBSTR .

Kucyki OMG
źródło
Dzięki. Bardzo elegancko! (dobrze wiedzieć też o REGEXP_SUBSTR.) Nawet nie pomyślałem, żeby szukać obsługi Regex w Oracle.
Precel
W Oracle możesz tworzyć funkcje (samodzielnie lub w pakiecie) i używać ich w instrukcji select.
bart
9
Niepowodzenie, jeśli jest uruchamiany z wartościami, które NIE zawierają podciągu, którego szukasz. instrzwraca 0, jeśli masz INSTR('ABC/D', '_'). Na końcu masz podciąg od 0 do (0-1), który jest zerowy. Niedobrze.
Marcel Stör
41

Można to łatwo zrobić za pomocą REGEXP_SUBSTR .

Proszę użyć

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

gdzie STRING_EXAMPLE to Twój ciąg.

Próbować:

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

To rozwiąże twój problem.

user1717270
źródło
1
Głosuję za tym razem z rozwiązaniem wybranym przez OP, ponieważ robi sztuczkę. Warto jednak zauważyć, że to rozwiązanie jest znacznie wolniejsze niż u Kucyków @OMG, zwłaszcza jeśli jest stosowane w warunkach. Moje testy wykazały około 6 razy wolniejsze wykonanie identycznego zapytania. To pytanie idzie jeszcze dalej w temacie stackoverflow.com/questions/41156391/ ...
Ister
W moich testach INSTRrozwiązanie działa prawie tak samo szybko jak REGEXProzwiązanie.
alexherm
7

Musisz uzyskać pozycję pierwszego podkreślenia (używając INSTR), a następnie pobrać część ciągu od pierwszego znaku do (pos-1) za pomocą 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

Dokumentacja instr

Dokumentacja Susbtr

Rajesh Chamarthi
źródło
6
SELECT REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1)  from dual

to właściwa odpowiedź opublikowana przez użytkownika 1717270

Jeśli użyjesz INSTR, poda pozycję dla ciągu, który zakłada, że ​​zawiera „_”. A jeśli nie? Cóż, odpowiedź będzie 0. Dlatego, jeśli chcesz wydrukować ciąg, wypisze on NULL. Przykład: jeśli chcesz usunąć domenę z „host.domain”. W niektórych przypadkach będziesz mieć tylko krótką nazwę, np. „Host”. Najprawdopodobniej chciałbyś wydrukować „host”. Cóż, przy INSTRjej pomocy otrzymasz znak, NULLponieważ nie znalazł żadnego ".", Czyli wydrukuje od 0 do 0. Dzięki REGEXP_SUBSTRtemu uzyskasz poprawną odpowiedź we wszystkich przypadkach:

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

GOSPODARZ

i

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

GOSPODARZ

Loquillo Amigo
źródło
0

Pamiętaj o tym, jeśli wszystkie twoje ciągi w kolumnie nie mają podkreślenia (... lub inaczej, jeśli wartością wyjściową będzie wartość null):

SELECT COALESCE
(SUBSTR("STRING_COLUMN" , 0, INSTR("STRING_COLUMN", '_')-1), 
"STRING_COLUMN") 
AS OUTPUT FROM DUAL
SJOH
źródło
0

Aby znaleźć dowolny podciąg z dużego ciągu:

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

Następnie, aby znaleźć ciąg 'Ple'z String_value, możemy zrobić tak:

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

Znajdziesz wynik: Ple

vishal Pathak
źródło
0

W przypadku, gdy pozycja łańcucha nie jest ustalona, ​​to poniższą instrukcją Select otrzymamy oczekiwany wynik.

Identyfikator struktury tabeli VARCHAR2 (100 bajtów) CLIENT VARCHAR2 (4000 bajtów)

Identyfikator danych KLIENT
1001 {"clientId": "con-bjp", "clientName": "ABC", "providerId": "SBS"}
1002 {"IdType": "AccountNo", "Id": "XXXXXXXX3521", "ToPricingId": "XXXXXXXX3521", "clientId": "Test-Cust", "clientName": "MFX"}

Wymaganie - Wyszukaj ciąg „ClientId” w kolumnie CLIENT i zwróć odpowiednią wartość. Na przykład From „clientId”: „con-bjp” -> con-bjp (oczekiwane wyjście)

select CLIENT, substr (substr (CLIENT, instr (CLIENT, '"clientId": "') + length ('" clientId ":"')), 1, instr (substr (CLIENT, instr (CLIENT, '"clientId") : "') + length ('" clientId ":" ')),' "', 1) -1) cut_str z TEST_SC;

KLIENT cut_str ------------------------------------------------ ----------- ---------- {"clientId": "con-bjp", "clientName": "ABC", "providerId": "SBS"} con- bjp {"IdType": "AccountNo", "Id": "XXXXXXXX3521", "ToPricingId": "XXXXXXXX3521", "clientId": "Test-Cust", "clientName": "MFX"} Test-Cust

Amit Vashishtha
źródło