SoundexESP

From PostgreSQL wiki
Jump to navigationJump to search

Library Snippets

Compute string soundex spanish

Works with PostgreSQL

Tested on 9.0, 9.1. Probably works in earlier versions

Written in

PL/pgSQL

Depends on

Nothing


Soundex Spanish is a function written to calculate soundex codes for spanish languages.

The soundex algorithm is written for english language, so it is not advisable to use it in other languages.

In my personal case, I needed a spanish version of the soundex algorithm, so, based on lfer work Soundex en Español, I made the PL/pgSQL version for the Spanish Soundex Algorithm.

Thanks to Grupo Vesica.


Hope this helps someone else:


-- oliver mazariegos http://www.grupovesica.com
CREATE OR REPLACE FUNCTION soundexesp(input text) RETURNS text
IMMUTABLE STRICT COST 500 LANGUAGE plpgsql
AS $$
DECLARE
	soundex text='';	
	-- para determinar la primera letra
	pri_letra text;
	resto text;
	sustituida text ='';
	-- para quitar adyacentes
	anterior text;
	actual text;
	corregido text;
BEGIN
       -- devolver null si recibi un string en blanco o con espacios en blanco
	if length(trim(input))= 0 then
		return null;
	end if;


	-- 1: LIMPIEZA:
		-- pasar a mayuscula, eliminar la letra "H" inicial, los acentos y la enie
		-- 'holá coñó' => 'OLA CONO'
		input=translate(ltrim(trim(upper(input)),'H'),'ÑÁÉÍÓÚÀÈÌÒÙÜ','NAEIOUAEIOUU');

		-- eliminar caracteres no alfabéticos (números, símbolos como &,%,",*,!,+, etc.
		input=regexp_replace(input, '[^a-zA-Z]', '', 'g');

	-- 2: PRIMERA LETRA ES IMPORTANTE, DEBO ASOCIAR LAS SIMILARES
	--  'vaca' se convierte en 'baca'  y 'zapote' se convierte en 'sapote'
	-- un fenomeno importante es GE y GI se vuelven JE y JI; CA se vuelve KA, etc
	pri_letra =substr(input,1,1);
	resto =substr(input,2);
	CASE 
		when pri_letra in ('V') then
			sustituida='B';
		when pri_letra in ('Z','X') then
			sustituida='S';
		when pri_letra in ('G') and substr(input,2,1) in ('E','I') then
			sustituida='J';
		when pri_letra in('C') and substr(input,2,1) not in ('H','E','I') then
			sustituida='K';
		else
			sustituida=pri_letra;

	end case;
	--corregir el parametro con las consonantes sustituidas:
	input=sustituida || resto;		

	-- 3: corregir "letras compuestas" y volverlas una sola
	input=replace(input,'CH','V');
	input=replace(input,'QU','K');
	input=replace(input,'LL','J');
	input=replace(input,'CE','S');
	input=replace(input,'CI','S');
	input=replace(input,'YA','J');
	input=replace(input,'YE','J');
	input=replace(input,'YI','J');
	input=replace(input,'YO','J');
	input=replace(input,'YU','J');
	input=replace(input,'GE','J');
	input=replace(input,'GI','J');
	input=replace(input,'NY','N');
	-- para debug:    --return input;

	-- EMPIEZA EL CALCULO DEL SOUNDEX
	-- 4: OBTENER PRIMERA letra
	pri_letra=substr(input,1,1);

	-- 5: retener el resto del string
	resto=substr(input,2);

	--6: en el resto del string, quitar vocales y vocales fonéticas
	resto=translate(resto,'@AEIOUHWY','@');
	
	--7: convertir las letras foneticamente equivalentes a numeros  (esto hace que B sea equivalente a V, C con S y Z, etc.)
	resto=translate(resto, 'BPFVCGKSXZDTLMNRQJ', '111122222233455677');
	-- así va quedando la cosa
	soundex=pri_letra || resto;

	--8: eliminar números iguales adyacentes (A11233 se vuelve A123)
	anterior=substr(soundex,1,1);
	corregido=anterior;
	
	FOR i IN 2 .. length(soundex) LOOP
		actual = substr(soundex, i, 1);
		IF actual <> anterior THEN
			corregido=corregido || actual;
			anterior=actual;			
		END IF;
	END LOOP;
	-- así va la cosa
	soundex=corregido;
	
	-- 9: siempre retornar un string de 4 posiciones
	soundex=rpad(soundex,4,'0');
	soundex=substr(soundex,1,4);		

	-- YA ESTUVO
	return soundex;	
END;	
$$

Example

db=#select soundexesp('ordoñez'),
       soundexesp('ordónez'),
       soundexesp('ordondes'),
       soundexesp('karla'),
       soundexesp('CARLA');


O635 | O635 | O635 | K640 | K640