2008-09-29 25 views
10

Estoy tratando de extraer cierta parte de una columna que está entre delimitadores.Buscar texto entre delimitadores en MySQL

p. Ej. foo encontrar en el 'esf

prueba siguiente: foo: bar

Así que en lo anterior me gustaría volver foo, pero todas las funciones de expresiones regulares sólo devuelven true | false, hay una manera de hacer esto en MySQL

Respuesta

18

Aquí ya go, las yemas:

SELECT 
    SUBSTR(column, 
    LOCATE(':',column)+1, 
     (CHAR_LENGTH(column) - LOCATE(':',REVERSE(column)) - LOCATE(':',column))) 
FROM table 

Sí, ni idea de por qué estás haciendo esto, pero esto va a hacer el truco.

Al realizar una LOCATE, podemos encontrar la primera ':'. Para encontrar el último ':', no hay una LOCALIZACIÓN inversa, entonces tenemos que hacerlo manualmente al realizar una LOCALIZACIÓN (':', REVERSE (columna)).

Con el índice del primer ':', el número de caracteres de la última ':' al final de la cadena, y la CHAR_LENGTH (no utilizan LONGITUD() para este), podemos use un poco de matemática para descubrir la longitud de la cadena entre las dos instancias de ':'.

De esta manera podemos peformAR un SUBSTR y eliminar dinámicamente los caracteres entre los dos ':'.

Una vez más, es asqueroso, pero para cada uno es suyo.

+1

Todo el hermoso monstruo. Bien hecho. –

+0

jajaja, si tuviera la oportunidad, arruinaría la Navidad. –

+0

¿A qué se refiere el 'nombre' en LOCATE (':', nombre)? –

2

Una combinación de LOCATE y MID haría probablemente el truco.

Si el valor " 'esf prueba: foo: bar" estaba en el campo fooField:

MID(fooField, LOCATE('foo', fooField), 3); 
+0

No sé lo que foo es, sólo sé los delimitadores: –

+0

Será un campo cada vez tener más de un conjunto de delimters? Y los delimitadores son: ¿verdad? –

+0

Eso es correcto. –

2

No sé si usted tiene este tipo de autoridad, pero si usted tiene para hacer consultas como esta podría ser hora de renormalizar sus tablas, y tener estos valores en una tabla de búsqueda.

+3

Podría estar tratando de extraer los datos para normalizarlo :-) –

+0

Eso es verdad. Buena llamada. :) –

0
select mid(col from locate(':',col) + 1 for 
locate(':',col,locate(':',col)+1)-locate(':',col) - 1) 
from table where col rlike ':.*:'; 
1

Con sólo un conjunto de delimitadores, lo siguiente debería funcionar:

SUBSTR(
    SUBSTR(fooField,LOCATE(':',fooField)+1), 
    1, 
    LOCATE(':',SUBSTR(fooField,LOCATE(':',fooField)+1))-1 
) 
0

Si conoce la posición que desea extraer de a diferencia de lo que los datos en sí es:

$colNumber = 2; //2nd position 
$sql = "REPLACE(SUBSTRING(SUBSTRING_INDEX(fooField, ':', $colNumber), 
          LENGTH(SUBSTRING_INDEX(fooField, 
                ':', 
                $colNumber - 1)) + 1)"; 
-2

puede utilizar la subcadena/función de localización en 1 mando

aquí es un tutorial ratones:

http://infofreund.de/mysql-select-substring-2-different-delimiters/

El comando como se describe su debe buscar u:

** SELECCIONAR substr (texto, Locate (':', texto) + 2, Locate (':', texto) - (Locate (':', texto) +2)) FROM testtable**

donde texto es el campo de texto que contiene " prueba 'esf: foo: bar "

Así que foo puede ser fooooo o fo - la duración no importa :).

3

Esto debería funcionar si los dos delimitadores solo aparecen dos veces en su columna. Estoy haciendo algo similar ...

substring_index(substring_index(column,':',-2),':',1) 
1
mid(col, 
    locate('?m=',col) + char_length('?m='), 
    locate('&o=',col) - locate('?m=',col) - char_length('?m=') 
) 

una forma compacta poco reemplazando char_length(.) con el número 3

mid(col, locate('?m=',col) + 3, locate('&o=',col) - locate('?m=',col) - 3) 

los patrones que he utilizado son '?m=' y '&o'.

0

Esto es lo que estoy extrayendo de (principalmente dos puntos ':' como delimitador pero algunas excepciones), como la columna theline255 en loaddata255 tabla:

23856.409:0023:trace:message:SPY_EnterMessage (0x2003a) L"{#32769}"  [0081] WM_NCCREATE sent from self wp=00000000 lp=0023f0b0 

Este es el código de MySQL (No pasó rápidamente lo que quiere y es sencillo):

select 
time('2000-01-01 00:00:00' + interval substring_index(theline255, '.', 1) second) as hhmmss 
, substring_index(substring_index(theline255, ':', 1), '.', -1) as logMilli 
, substring_index(substring_index(theline255, ':', 2), ':', -1) as logTid 
, substring_index(substring_index(theline255, ':', 3), ':', -1) as logType 
, substring_index(substring_index(theline255, ':', 4), ':', -1) as logArea 
, substring_index(substring_index(theline255, ' ', 1), ':', -1) as logFunction 
, substring(theline255, length(substring_index(theline255, ' ', 1)) + 2) as logText 
from loaddata255 

y este es el resultado:

# LogTime, LogTimeMilli, LogTid, LogType, LogArea, LogFunction, LogText 
'06:37:36', '409', '0023', 'trace', 'message', 'SPY_EnterMessage', '(0x2003a) L\"{#32769}\"  [0081] WM_NCCREATE sent from self wp=00000000 lp=0023f0b0' 
0

Este me parece elegante. Pele todo después del separador n-ésimo, gire la cuerda, pele todo después de 1. separador, gire hacia atrás.

select 
    reverse(
    substring_index(
     reverse(substring_index(str,separator,substrindex)), 
     separator, 
     1) 
); 

Por ejemplo:

select 
    reverse(
    substring_index(
     reverse(substring_index('www.mysql.com','.',2)), 
     '.', 
     1 
    ) 
); 
Cuestiones relacionadas