Estou tentando converter esse algoritmo Levenshtein Distance do MySQL para o SQL Server.
Estou preso CONCAT(@cv1, UNHEX(HEX(@j)))
e CONV(HEX(SUBSTRING(@cv1, @j, 1)), 16, 10)
não conheço funções equivalentes no SQL Server para HEX (), UNHEX () e CONV (). ACHO que posso usar CONVERT()
, mas não tenho certeza de como.
Aqui está o que eu tenho:
CREATE FUNCTION fn_FuzzyMatch(
@str1 varchar(max),
@str2 varchar(max) )
RETURNS int
AS
BEGIN
DECLARE
@str1_len int,
@str2_len int,
@i int,
@j int,
@c int,
@c_temp int,
@cost int,
@str1_char char,
@cv0 varbinary(max),
@cv1 varbinary(max);
SELECT
@str1_len = SDU_Tools.StringLength(@str1),
@str2_len = SDU_Tools.StringLength(@str2),
@cv1 = 0x00,
@j = 1,
@i = 1,
@c = 0;
IF @str1 = @str2
RETURN 0;
ELSE IF @str1_len = 0
RETURN @str2_len;
ELSE IF @str2_len = 0
RETURN @str1_len;
ELSE
BEGIN
WHILE @j <= @str2_len
BEGIN
SET @cv1 = CONCAT(@cv1, UNHEX(HEX(@j)));
SET @j = @j + 1;
END;
WHILE @i <= @str1_len
BEGIN
SELECT
@str1_char = SUBSTRING(@str1, @i, 1),
@c = @i,
@cv0 = UNHEX(HEX(@i)),
@j = 1;
WHILE @j <= @str2_len
BEGIN
SET @c = @c + 1;
IF @str1_char = SUBSTRING(@str2, @j, 1)
SET @cost = 0;
ELSE
SET @cost = 1;
SET @c_temp = CONV(HEX(SUBSTRING(@cv1, @j, 1)), 16, 10) + @cost;
IF @c > @c_temp
SET @c = @c_temp;
SET @c_temp = CONV(HEX(SUBSTRING(@cv1, @j+1, 1)), 16, 10) + 1;
IF @c > @c_temp
SET @c = @c_temp;
SET @cv0 = CONCAT(@cv0, UNHEX(HEX(@c)))
SET @j = @j + 1;
END;
SET @cv1 = @cv0
SET @i = @i + 1;
END;
END;
RETURN @c;
END
Role para baixo no adendo abaixo.
Resposta original:
A combinação MySQL
UNHEX(HEX(integer-value))
está convertendo um código ASCII inteiro pequeno em um caractere ASCII. O equivalente do SQL Server éCHAR(integer-value)
. Isso converteria 0 em um caractere de controle NUL, 1 em SOH e 55 no dígito ASCII "7".A combinação MySQL
CONV(HEX(character-value), 16, 10)
está fazendo o inverso, convertendo um caractere ASCII em código de caractere ASCII. O equivalente do SQL Server éASCII(character-value)
. Isso converteria um caractere de controle NUL em 0, um SOH em 1 e o dígito ASCII '7' em 55.Parece que sua função está usando essas operações para mapear números inteiros de e para uma sequência de caracteres que simula uma matriz ou números inteiros. Como esses valores parecem estar relacionados ao comprimento das strings de entrada, o algoritmo provavelmente está limitado a strings com no máximo 255 caracteres. Não analisei seu uso além disso.
Veja o seguinte: fiddle1 e fiddle2 .
Termo aditivo :
Depois de dar uma olhada, vejo que o código MySQL também está realizando conversões implícitas entre char e binário. Minha resposta revisada segue.
A combinação do MySQL
UNHEX(HEX(integer-value))
está convertendo um código ASCII inteiro pequeno em um caractere ASCII que é então convertido implicitamente em um valor binário. O equivalente do SQL Server éCONVERT(BINARY(1), integer-value)
. Isso converteria 0 em 0x00, 1 em 0x01 e 255 em 0xFF.A combinação do MySQL
CONV(HEX(binary-value), 16, 10)
está fazendo o inverso, convertendo implicitamente o binário em um caractere e, em seguida, esse caractere no código de caracteres ASCII. O equivalente do SQL Server éCONVERT(INT, binary(1)-value)
. Isso converteria 0x00 em 0, 0x01 em 1 e 0xff em 255.Parece que sua função está usando essas operações para mapear números inteiros de e para uma string binária que simula uma matriz ou números inteiros. Como esses valores são limitados a 255 e parecem estar relacionados ao comprimento das strings de entrada, o algoritmo provavelmente está limitado a strings com no máximo 255 caracteres.
Veja este db<>fiddle que aplica ambas as versões das substituições acima (e algumas outras alterações mínimas) à sua função. Também inclui duas das soluções da distância de Levenshtein vinculada na questão T-SQL identificada por DaleK nos comentários.
Resultados da amostra: