O.T. MySQL Ocurrencia de un caracter dentro de una cadena

1,616 views
Skip to first unread message

Julio Cesar Vente Ruiz

unread,
Jul 26, 2012, 11:40:31 AM7/26/12
to publice...@googlegroups.com
Hola comunidad, actualmente trabajo con MySQL para las tres aplicaciones que manejo, y el día de hoy me encuentro que necesito saber desde MySQL saber cuantas veces esta un caracter dentro de una cadena de caracteres...

Ejemplo:  "a"  dentro de "Magdalena" esta 3 veces,  necesito obtener esto pero con una consulta de SQL, es decir si existe una funcion de MySQL que lo haga..

Saludos.. y gracias de antemano.. 

P.D. este es mi primer O.T..

ZorroAstro

unread,
Jul 26, 2012, 12:18:08 PM7/26/12
to publice...@googlegroups.com
Podrias usar una funcion si usas VFP

Por Ejemplo
*****************
***Donde "buscar" es lo que buscas
***Tabla.nombre es el campo de la tabla donde buscar
*****************
buscar = "a"

SELECT buscar,;
       tabla.nombre,;
       contar_letras(buscar,tabla.nombre) as cuenta;
       FROM tabla;
       WHERE !ISNULL(tabla.nombre);
       INTO CURSOR xcursor
      
FUNCTION contar_letras(campo,expresion)
RETURN OCCURS(campo,expresion)

Espere te sirva la idea......

Julio Cesar Vente Ruiz

unread,
Jul 26, 2012, 12:47:29 PM7/26/12
to publice...@googlegroups.com
Gracias  ZorroAstro  por contestar, pero recuerda que la base de datos es MySQL no puedo enviar una funcion de FOX en la sentencia a MySQL porque no la entendería...



--
 
 
 



--


Julio Cesar Vente Ruiz

Richard Gaviria

unread,
Jul 26, 2012, 1:46:46 PM7/26/12
to publice...@googlegroups.com
Bueno en teoría si puedes todo lo que envíes antecedido con el signo "?" va a ser analizado primero por Visual FoxPro y luego el resultado de esto enviado al servidor de datos, por ejemplo:

TEXT TO lcSQL NOSHOW
     insert into catos (paterno,materno,nombres) values (?alltrim(thisform.Text1.Value), ?alltrim(thisform.Text2.Value) ,?alltrim(thisform.Text3.Value) )
ENDTEXT

=SqlExec(nombconn,lcSQL)

Saludos

Rick.



Date: Thu, 26 Jul 2012 11:47:29 -0500
Subject: Re: [vfp] Re: O.T. MySQL Ocurrencia de un caracter dentro de una cadena
From: jvent...@gmail.com
To: publice...@googlegroups.com
--
 
 
 

Pablo Daniel Lissa

unread,
Jul 26, 2012, 2:04:35 PM7/26/12
to publice...@googlegroups.com
Hola:

No conozco una función en MySQL para hacer eso. Yo traería de la Base de Datos los registros que contengan el caracter buscado y luego calcularía las ocurrencias.

La consulta sería algo como:
    SELECT cadena FROM tabla WHERE cadena LIKE '%a%'

Y con eso en un cursor (cursor_cadenas, supongamos), haría otro SELECT (local), de la forma:
    SELECT cadena, OCCURS(cadena, 'a') as contador_caracteres FROM cursor_cadenas GROUP BY cadena

Igualmente, una consulta así repercutiría negativamente en el rendimiento.

Saludos.
-----------------------------------------------------------------------------------------------------

Walter R. Ojeda Valiente

unread,
Jul 26, 2012, 3:22:25 PM7/26/12
to publice...@googlegroups.com
Con Firebird puedes crear tus propias funciones externas para que hagan cualquier cosa que desees, supongo que Mysql tendrá algo parecido.

Saludos.

Walter.





Date: Thu, 26 Jul 2012 08:40:31 -0700
From: jvent...@gmail.com
To: publice...@googlegroups.com
Subject: [vfp] O.T. MySQL Ocurrencia de un caracter dentro de una cadena
--
 
 
 

Víctor Hugo Espínola Domínguez

unread,
Jul 26, 2012, 3:52:22 PM7/26/12
to publice...@googlegroups.com
Hola Julio César

MySql no tiene una función que calcule éso. Pero puedes definirla usando alguna de estas funciones: LOCATE, MID o SUBSTRING.
El siguiente código muestra cómo hacerlo con LOCATE. OJO!, puede que hayan algunos errores de sintaxis, porque yo no lo probé, pero la idea es ésta:

CREATE FUNCTION sp_CntCarTxt ( IN tcCar CHAR(1), IN tcTxt VARCHAR( 255 ) )

    RETURNS INT

    BEGIN
          DECLARE lnCntCarTxt , lnPosIni, lnPosTmp  INT;

          SET lnCntCarTxt = 0;
          SET lnPosIni = LOCATE( tcCar, tcTxt );
          WHILE lnPosIni > 0
                  SET lnCntCarTxt = lnCntCarTxt + 1;
                  SET lnPosTmp = lnPosIni + 1;
                  SET lnPosIni = LOCATE( tcCar, tcTxt, lnPosTmp );
          END WHILE;

          RETURN lnCntCarTxt;

    END;

Saludos.
Víctor.

--
 
 
 

Fox Reloaded

unread,
Jul 26, 2012, 4:20:55 PM7/26/12
to publice...@googlegroups.com
Bueno la solucion de Victor Hugo me gusta porque no genera tanto codigo, ahora que voy viendo el problema me causo curiosidad y escribi un procedimiento que hace lo que quieres enviando dos parametros. Lo acabo de probar y me funciona normal.

Ahi esta el codigo fuente:

CREATE PROCEDURE charCounter(IN cadena CHAR(30), IN matcher CHAR(1))
BEGIN
DECLARE nParamCount INT(3) DEFAULT 0;
DECLARE nActPos INT(3) DEFAULT 1;
DECLARE nCounter INT(3) DEFAULT 0;
DECLARE cChar CHAR(1);
declare cMatch CHAR(1);
SET nParamCount = CHAR_LENGTH(cadena);
SET cMatch = TRIM(LOWER(matcher));
SET nCounter = 0;
REPEAT
SET cChar = TRIM(LOWER(SUBSTRING(cadena,nActPos,1)));
IF STRCMP(cChar,cMatch) = 0 THEN
SET nCounter = nCounter + 1;
END IF;
SET nActPos = nActPos + 1;
UNTIL nActPos = nParamCount +1 
END REPEAT;
SELECT nCounter; 
END
//
No te olvides de establecer un delimitador al principio y cambiarlo al final.

Delimeter // (esto es antes de escribir el procedimiento en el servidor)

Delimiter ; (esto es al finalizar de escribir el procedimiento en el servidor)

Para llamarlo desde Fox.

lcCaracter = 'Magdalena'
lcMatchChar = 'a'

SQLEXEC(P1,"Call charcounter(?lcCaracter,?lcMatchChar)",'cursor')
browse cursor

Espero que te ayude.
-- 
Thank you for everything... :)


----  Christian Torres ----
* * * * Venezuela * * * *

Julio Cesar Vente Ruiz

unread,
Jul 26, 2012, 10:15:48 PM7/26/12
to publice...@googlegroups.com
Antes que nada muchas gracias a todos por sus respuestas, la verdad me complace mucho la atención.
La verdad como dice Fox Reloaded, la solucion de de Victor H se ve mas limpia y de menos código pero al parecer es igual.

La función de Victor H ya probada corrigiendo los temas de sintaxis es:


DELIMITER $$

CREATE FUNCTION sp_CntCarTxt(tcCar CHAR(1), tcTxt VARCHAR(255) ) RETURNS INT(3)

    BEGIN
          DECLARE lnCntCarTxt INT(3);
          DECLARE lnPosIni INT(3);
          DECLARE lnPosTmp INT(3);

          SET lnCntCarTxt = 0;
          SET lnPosIni = (SELECT LOCATE(tcCar,tcTxt)) ;
          WHILE lnPosIni > 0 DO
                  SET lnCntCarTxt = lnCntCarTxt + 1;
                  SET lnPosTmp = lnPosIni + 1;
                  SET lnPosIni = (SELECT LOCATE(tcCar,tcTxt,lnPosTmp));
          END WHILE;

          RETURN lnCntCarTxt;

    END$$

DELIMITER ;

-- Para ejecutarla:
SELECT sp_CntCarTxt("a","Magdalena");


Muchas gracias Victor H y Fox R.


--
 
 
 

Fox Reloaded

unread,
Jul 27, 2012, 10:07:42 AM7/27/12
to publice...@googlegroups.com
Hey Ojo una advertencia o sugerencia todo es como lo quieran tomar, según mi experiencia en C no todo el código que sea corto quiera decir que sea mas eficiente, que se vea mas limpio es otra cosa. El caso es que una función o procedimiento se puede evaluar en su capacidad de expansión sin la modificación del código original, eso es lo que lleva a muchos programas a ser mas fáciles de mantener...

Habiendo aclarado mi punto.

Feliz día para todos... :)

Julio Cesar Vente Ruiz

unread,
Jul 27, 2012, 7:55:52 PM7/27/12
to publice...@googlegroups.com

Buen punto....

--
 
 
 
Reply all
Reply to author
Forward
0 new messages