¿Cómo seleccionar una subcadena en Oracle SQL hasta un carácter específico?

82

Digamos que tengo una columna de tabla que tiene resultados como:

ABC_blahblahblah
DEFGH_moreblahblahblah
IJKLMNOP_moremoremoremore

Me gustaría poder escribir una consulta que seleccione esta columna de dicha tabla, pero solo devuelva la subcadena hasta el carácter de subrayado (_). Por ejemplo:

ABC
DEFGH
IJKLMNOP

La función SUBSTRING no parece estar a la altura de la tarea porque se basa en la posición y la posición del guión bajo varía.

Pensé en la función TRIM (la función RTRIM específicamente):

SELECT RTRIM('listofchars' FROM somecolumn) 
FROM sometable

Pero no estoy seguro de cómo haría que esto funcione, ya que solo parece eliminar una cierta lista / conjunto de caracteres y en realidad solo estoy detrás de los caracteres que conducen al carácter subrayado.

Galleta salada
fuente

Respuestas:

141

El uso de una combinación de SUBSTR, INSTR y NVL (para cadenas sin un guión bajo) devolverá lo que desea:

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

Resultado:

output
------
ABC

Utilizar:

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

Referencia:

Apéndice

Si usa Oracle10g +, puede usar expresiones regulares a través de REGEXP_SUBSTR .

Ponis dios mio
fuente
Gracias. ¡Muy elegante! (También es bueno saber sobre REGEXP_SUBSTR). Ni siquiera pensé en buscar soporte para Regex en Oracle.
Pretzel
En Oracle puede crear funciones (independientes o en un paquete) y usarlas en una instrucción de selección.
Bart
9
Falla si se ejecuta con valores que NO contienen la subcadena que está buscando. instrdevuelve 0 si lo tiene INSTR('ABC/D', '_'). Al final, tiene una subcadena de 0 a (0-1) que es nula. No está bien.
Marcel Stör
40

Esto se puede hacer usando REGEXP_SUBSTR fácilmente.

Por favor use

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

donde STRING_EXAMPLE es su cadena.

Tratar:

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

Resolverá tu problema.

usuario1717270
fuente
1
Estoy votando esto junto con la solución elegida por OP, ya que hace un truco. Sin embargo, vale la pena señalar que esta solución es mucho más lenta que la de @OMG Ponies, especialmente si se usa en condiciones específicas. Mis pruebas han mostrado un rendimiento 6 veces más lento de consultas idénticas. Esta pregunta va aún más lejos en el tema stackoverflow.com/questions/41156391/…
Ister
En mis pruebas, la INSTRsolución funciona con la misma rapidez que la REGEXPsolución.
alexherm
7

Debe obtener la posición del primer guión bajo (usando INSTR) y luego obtener la parte de la cadena desde el primer carácter hasta (pos-1) usando 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

Documentación instr

Documentación de Susbtr

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

es la respuesta correcta, según lo publicado por user1717270

Si lo usa INSTR, le dará la posición de una cadena que asume que contiene "_" en ella. ¿Y si no es así? Bueno, la respuesta será 0. Por lo tanto, cuando desee imprimir la cadena, imprimirá un NULL. Ejemplo: si desea eliminar el dominio de un "host.domain". En algunos casos, solo tendrá el nombre corto, es decir, "host". Lo más probable es que desee imprimir "host". Bueno, con INSTRél te dará un NULLporque no encontró ningún ".", Es decir imprimirá de 0 a 0. Con REGEXP_SUBSTRobtendrás la respuesta correcta en todos los casos:

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

ANFITRIÓN

y

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

ANFITRIÓN

Loquillo Amigo
fuente
0

Recuerde esto si todas sus cadenas en la columna no tienen un guión bajo (... o si el valor nulo será la salida):

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

Para encontrar cualquier subcadena de una cadena grande:

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

Luego, para encontrar la cadena 'Ple'de String_valuepodemos hacer lo siguiente:

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

Encontrarás resultado: Ple

vishal Pathak
fuente
0

En caso de que la posición de la cadena no sea fija, por debajo de la instrucción Select podemos obtener la salida esperada.

Estructura de la tabla ID VARCHAR2 (100 BYTE) CLIENT VARCHAR2 (4000 BYTE)

Data- ID CLIENTE
1001 {"clientId": "con-bjp", "clientName": "ABC", "providerId": "SBS"}
1002 {"IdType": "AccountNo", "Id": "XXXXXXXX3521", "ToPricingId": "XXXXXXXX3521", "clientId": "Test-Cust", "clientName": "MFX"}

Requisito: busque la cadena "ClientId" en la columna CLIENTE y devuelva el valor correspondiente. Como de "clientId": "con-bjp" -> con-bjp (Salida esperada)

seleccione CLIENTE, substr (substr (CLIENT, instr (CLIENT, '"clientId": "') + length ('" clientId ":"')), 1, instr (substr (CLIENT, instr (CLIENT, '"clientId" : "') + length ('" clientId ":" ')),' "', 1) -1) cut_str de TEST_SC;

CLIENT 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
fuente