我需要實作一個函式來查找相似的名稱。這是為了開發一個遷移了以前系統的資料的新系統。其中一項功能是在創建帳戶時,它會嘗試查找具有相似名稱的人員記錄并提出建議。“John Johnson”的類似名稱的示例可能是:
- 約翰·約翰遜
- 喬恩·瓊森
- 約翰和簡·約翰遜-彼得斯
- 家庭。約翰森
- J·約翰遜
為了實作這一點,我創建了一些 SQL 函式,并且它們在功能上起作用:
根據我拼錯的名字,找到這條記錄需要 12-13 秒,這當然太長了。目前全表只有 512 條記錄。對提高性能有任何幫助嗎?我知道在 SQL 中不推薦回圈,所以可能會有一些收獲。我不是 DBA 或 SQL 專家,不知道如何在沒有回圈的情況下撰寫不同的代碼。沒想到我可以使用連接,因為沒有平等。
uj5u.com熱心網友回復:
在執行 OP 評論中的建議后,我設法將相同的 SELECT 陳述句從 12-13 秒減少到大約 1 秒,這更容易接受。
SplitString 已更改為行內函式:
Create FUNCTION [dbo].[SplitString]( @s nvarchar(4000) ) RETURNS TABLE WITH SCHEMABINDING AS RETURN( SELECT TRIM(value) AS value FROM STRING_SPLIT(REPLACE(REPLACE(REPLACE(REPLACE(@s, '/', '-'),'&', '-'),' ', '-'),'\', '-'), '-', NULL) WHERE RTRIM(value) <> '' );減少變數并為 IsSimilar 函式使用 Join 陳述句也可以提高:
CREATE FUNCTION [dbo].[IsSimilar]( @s nvarchar(4000) , @t nvarchar(4000) ) RETURNS BIT AS BEGIN IF (@s = 'fam' OR @s = 'fam.' OR @t = 'fam' OR @t = 'fam.') return 1 IF (LEN(TRIM(@s)) > 0 AND LEN(TRIM(@t)) > 0) BEGIN RETURN (SELECT IIF (EXISTS(SELECT [sT].[value] FROM (SELECT [value] FROM [dbo].[SplitString](@s)) AS sT INNER JOIN (SELECT [value] FROM [dbo].[SplitString](@t)) AS tT ON (((LEN([sT].[value]) = 1 OR LEN([tT].[value]) = 1 OR SUBSTRING([sT].[value], 2, 1) IN ('.', ' ') OR SUBSTRING([tT].[value], 2, 1) IN ('.', ' ')) AND SUBSTRING([sT].[value], 1, 1) = SUBSTRING([tT].[value], 1, 1)) OR (NOT(SUBSTRING([sT].[value], 2, 1) IN ('.', ' ') OR SUBSTRING([tT].[value], 2, 1) IN ('.', ' ')) AND (SELECT [dbo].[Levenshtein]([sT].[value],[tT].[value], 5)) IS NOT NULL)) ), 1, 0)) END RETURN 0 END我不知道這種提升對真正的大資料有多大影響,但在這種情況下,情況并非如此,因為每個新帳戶創建都會將個人記錄鏈接到帳戶記錄,并且只有 AccountID = NULL 的個人記錄才會被考慮。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/425850.html
