SQL UDF - Calculate Distance Between Strings (Levenshtein)
This is basically a sql vairant to calculate % of closeness of strings, Not same as Fuzzy Match in python, This incorporates levenshtein Logic
a. Main Logic
CREATE FUNCTION [dbo].[Levenshtein](@s1 NVARCHAR(MAX), @s2 NVARCHAR(MAX))
RETURNS INT
AS
BEGIN
DECLARE @lenS1 INT = LEN(@s1),
@lenS2 INT = LEN(@s2),
@i INT,
@j INT,
@cost INT;
-- Table variable to store distances
DECLARE @d TABLE (i INT, j INT, cost INT);
-- Initialize distances
-- Fill for @i (vertical)
SET @i = 0;
WHILE @i <= @lenS1
BEGIN
INSERT INTO @d (i, j, cost) VALUES (@i, 0, @i);
SET @i = @i + 1;
END
-- Fill for @j (horizontal)
SET @j = 0;
WHILE @j <= @lenS2
BEGIN
INSERT INTO @d (i, j, cost) VALUES (0, @j, @j);
SET @j = @j + 1;
END
-- Fill matrix for distances
SET @i = 1;
WHILE @i <= @lenS1
BEGIN
SET @j = 1;
WHILE @j <= @lenS2
BEGIN
SET @cost = CASE
WHEN SUBSTRING(@s1, @i, 1) = SUBSTRING(@s2, @j, 1) THEN 0
ELSE 1
END;
DECLARE @cost1 INT, @cost2 INT, @cost3 INT;
-- Retrieve costs for comparison
SELECT @cost1 = cost FROM @d WHERE i = @i - 1 AND j = @j; -- Deletion
SELECT @cost2 = cost FROM @d WHERE i = @i AND j = @j - 1; -- Insertion
SELECT @cost3 = cost FROM @d WHERE i = @i - 1 AND j = @j - 1; -- Substitution
-- Calculate the minimum of the three values and insert into table
INSERT INTO @d (i, j, cost)
VALUES (@i, @j,
(SELECT MIN(val)
FROM (VALUES (@cost1 + 1), (@cost2 + 1), (@cost3 + @cost)) AS value(val))
);
SET @j = @j + 1;
END
SET @i = @i + 1;
END
-- Return final distance (bottom-right corner of the matrix)
RETURN (SELECT cost FROM @d WHERE i = @lenS1 AND j = @lenS2);
END;
GO
b. % Calculation
CREATE FUNCTION [dbo].[Levenshtein_Percentage] (@str1 NVARCHAR(MAX), @str2 NVARCHAR(MAX))
RETURNS DECIMAL(10,2)
as
begin
RETURN (
SELECT
(1.0 - CAST(dbo.Levenshtein(@str1, @str2) AS FLOAT) / CAST(GREATEST(LEN(@str1), LEN(@str2)) AS FLOAT)) * 100 AS SimilarityPercentage)
END;
GO
Usage:
select [dbo].[Levenshtein_Percentage]('hello','dubmo')
20.00
select [dbo].[Levenshtein_Percentage]('hello','zyx')
0.00
select [dbo].[Levenshtein_Percentage]('hello','hello dear')
50.00
select [dbo].[Levenshtein_Percentage]('hello','hellox')
83.33
select [dbo].[Levenshtein_Percentage]('hello','HELLo')
100.00