Já resolvi aqui a questão.

Segue o que eu implementei com base em um código que encontrei na Net
(mas fechei a aba e estava em modo anônimo, perdi qual era - créditos
para outra pessoa).

Coloquei o peso do Ç igual ao peso de C que é igual ao peso de S e de
X e coloquei o ÃO e ÕE com o peso de M caso o cara tenha escrito um
JOAUM ao invés de JOÃO.

Só respondendo: não quero ser muito flexível, por isso eliminei uma
penca de coisas e deixei o índice apenas como <= 1. E sim, o cadastro
de detentos é sempre feito com o nome completo. Só para te dar uma
base de como ficou bacana, o teste foi assim:

SELECT LATINEX('Joaum Culioins da Çilva Roxa'), LATINEX('João Culhões
da Silva Rocha');

Veja que a assinatura de ambos é idêntica.

Meu problema está apenas com o raio da letra W que pode ter som de V
ou se U como em Wallace e Watson. Nesse caso a assinatura de todo o
restante é idêntica, exceto a primeira letra. Não posso descartar, mas
posso colocar uma margem de 1 se eu simplesmente pegar os resultados
como parte de levenschtein e manter o índice em <= 1. Acredito que
isso me ajude também a pegar similaridades como Jasmin e Yasmin.

Assim, eis o que eu tenho:

-- Resultado levenshtein = 0, porque o primeiro caractere é idêntico
SELECT LEVENSHTEIN(LATINEX('Joaum Culioins da Çilva Roxa'),
LATINEX('João Culhões da Silva Rocha'))

-- Resultados levenshtein = 1, porque o primeiro caractere é o único que
SELECT LEVENSHTEIN(LATINEX('Uólaci Culioins da Çilva Roxa'),
LATINEX('Wallace Culhões da Silva Rocha'))
SELECT LEVENSHTEIN(LATINEX('Wanezza Culioins da Çilva Roxa'),
LATINEX('Vanessa Culhões da Silva Rocha'))
SELECT LEVENSHTEIN(LATINEX('Amiltão Culioins da Çilva Roxa'),
LATINEX('Hamilton Culhões da Silva Rocha'))

--Criação da função de peso do som das consoantes para cálculo de soundex latin

CREATE OR REPLACE FUNCTION pesom(CHARACTER)
 RETURNS INTEGER AS
$BODY$

SELECT
    CASE $1
      WHEN 'B' THEN 1
      WHEN 'C' THEN 2
      WHEN 'D' THEN 3
      WHEN 'F' THEN 1
      WHEN 'G' THEN 2
      WHEN 'J' THEN 2
      WHEN 'K' THEN 2
      WHEN 'L' THEN 4
      WHEN 'M' THEN 5
      WHEN 'N' THEN 5
      WHEN 'P' THEN 1
      WHEN 'Q' THEN 2
      WHEN 'R' THEN 6
      WHEN 'S' THEN 2
      WHEN 'T' THEN 3
      WHEN 'V' THEN 1
      WHEN 'X' THEN 2
      WHEN 'Z' THEN 2
      ELSE 0
END

$BODY$
LANGUAGE 'sql' VOLATILE
COST 100;

ALTER FUNCTION pesom(CHARACTER) OWNER TO postgres;


--Criação da função de peso do som das consoantes para cálculo de soundex latin


CREATE OR REPLACE FUNCTION latinex(CHARACTER VARYING)
RETURNS CHARACTER AS
$BODY$

DECLARE
texto VARCHAR;
resultado VARCHAR;
i INT;
ipesom INT;
valorPrimeiraLetra INT;

BEGIN

texto = $1;
texto = UPPER(texto);
texto = TRANSLATE(texto, 'ãO', 'M');
texto = TRANSLATE(texto, 'ÃO', 'M');
texto = TRANSLATE(texto, 'õE', 'M');
texto = TRANSLATE(texto, 'ÕE', 'M');
texto = TRANSLATE(texto, 'ñ', 'N');
texto = TRANSLATE(texto, 'Ñ', 'N');
texto = TRANSLATE(texto, 'ç', 'C');
texto = TRANSLATE(texto, 'Ç', 'C');

resultado = SUBSTRING(texto,1,1);

valorPrimeiraLetra = pesom(resultado);

i=2;


WHILE i < LENGTH(texto) LOOP

ipesom = pesom(SUBSTRING(texto, i, 1));

IF (NOT (ipesom = 0) AND NOT (valorPrimeiraLetra = ipesom)) THEN
resultado = resultado || ipesom;
END IF;

valorPrimeiraLetra = ipesom;

ipesom = 0;

i := i + 1;

END LOOP;

WHILE LENGTH(resultado) < 4 LOOP
resultado = resultado || '0';
END LOOP;

RETURN resultado;

END;

$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;

ALTER FUNCTION latinex(CHARACTER VARYING) OWNER TO postgres;

Em 10 de julho de 2013 11:13, Euler Taveira <[email protected]> escreveu:
> On 10-07-2013 10:23, Pablo Sánchez wrote:
>> Até o momento, tudo quase ok (tirando o fato de que não é para idiomas
>> latinos, mas já é algo). Só que fiquei com dúvida sobre qual seria um
>> bom valor para o índice Levenshtein. Estou extremamente compelido pelo
>> índice 3, mas gostaria de opiniões.
>>
> Não existe índice bom ou ruim; tudo depende de (i) seus dados e (ii) o
> quão flexível você quer ser. Faça bastante testes em uma "baseline" e
> decida qual é o ideal.
>
>> Eis um exemplo de teste que mostrou-se satisfatório
>>
>> select soundex('Josefa Silva'), soundex('Joseph Silva');
>> select levenshtein('Josefa Silva', 'Joseph Silva');
>> select metaphone('Josefa Silva', 10), metaphone('Joseph Silva', 10);
>> select dmetaphone('Josefa Silva'), dmetaphone('Joseph Silva');
>> select dmetaphone_alt('Josefa Silva'), dmetaphone_alt('Joseph Silva');
>>
> Eu não aconselharia utilizar qualquer dessas funções em nomes completos.
> O soundex, por exemplo, considera somente algumas posições (no mínimo 4
> caracteres). O levenshtein utilizado com strings longas podem ter mais
> do que 3 ou 4 mudanças. Ao invés disso, quebre o nome completo em nome e
> sobrenome e faça uma comparação individual ou utilize uma composição de
> funções de similaridade.
>
> Se você quer usar funções por similaridade, eu aconselho dar uma olhada
> no pg_similarity [1]. Ele contém uma série de funções que podem te
> auxiliar na tarefa de casamento flexível de strings.
>
>
> [1] https://github.com/eulerto/pg_similarity
>
>
> --
>    Euler Taveira                   Timbira - http://www.timbira.com.br/
>    PostgreSQL: Consultoria, Desenvolvimento, Suporte 24x7 e Treinamento
> _______________________________________________
> pgbr-geral mailing list
> [email protected]
> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral



-- 





Pablo Santiago Sánchez
ZCE ZEND006757
[email protected]
(61) 9975-0883
http://www.sansis.com.br
"Pluralitas non est ponenda sine necessitate"
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a