sql - 在 SQL 中的部分字符串上使用 levenshtein
问题描述
我试图找出一种使用 Levenshtein 方法将一些模糊搜索方法用于我们的店面搜索字段的方法,但我遇到了如何仅搜索部分产品名称的问题。
例如,客户搜索scisors
,但我们有一个名为 的产品electric scissor
。使用 Levenshtein 方法levenshtein("scisors","electric scissor")
,我们将得到 11 的结果,因为电气部分将被计为差异。
我正在寻找的是一种查看产品名称子字符串的方法,因此它将与它进行比较levenshtein("scisors","electric")
,然后还levenshtein("scisors","scissor")
可以看到我们在第二个子字符串中只能得到 2 的结果,从而将该产品显示为他们的搜索结果的一部分。
非工作示例让您了解我所追求的:
SELECT * FROM products p WHERE levenshtein("scisors", p.name) < 5
问题:有没有办法编写一个处理检查字符串部分的 SQL 语句?我是否需要在我的数据库中创建更多函数才能处理它或修改我现有的函数,如果是这样,它会是什么样子?
我目前正在使用 levenshtein 方法的这个实现:
//levenshtein(s1 as VARCHAR(255), s2 as VARCHAR(255))
//returns int
BEGIN
DECLARE s1_len, s2_len, i, j, c, c_temp, cost INT;
DECLARE s1_char CHAR;
-- max strlen=255
DECLARE cv0, cv1 VARBINARY(256);
SET s1_len = CHAR_LENGTH(s1), s2_len = CHAR_LENGTH(s2), cv1 = 0x00, j = 1, i = 1, c = 0;
IF s1 = s2 THEN
RETURN 0;
ELSEIF s1_len = 0 THEN
RETURN s2_len;
ELSEIF s2_len = 0 THEN
RETURN s1_len;
ELSE
WHILE j <= s2_len DO
SET cv1 = CONCAT(cv1, UNHEX(HEX(j))), j = j + 1;
END WHILE;
WHILE i <= s1_len DO
SET s1_char = SUBSTRING(s1, i, 1), c = i, cv0 = UNHEX(HEX(i)), j = 1;
WHILE j <= s2_len DO
SET c = c + 1;
IF s1_char = SUBSTRING(s2, j, 1) THEN
SET cost = 0; ELSE SET cost = 1;
END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j, 1)), 16, 10) + cost;
IF c > c_temp THEN SET c = c_temp; END IF;
SET c_temp = CONV(HEX(SUBSTRING(cv1, j+1, 1)), 16, 10) + 1;
IF c > c_temp THEN
SET c = c_temp;
END IF;
SET cv0 = CONCAT(cv0, UNHEX(HEX(c))), j = j + 1;
END WHILE;
SET cv1 = cv0, i = i + 1;
END WHILE;
END IF;
RETURN c;
END
解决方案
这是一个有点长的评论。
首先,我建议使用带有同义词列表的全文搜索。也就是说,您的用户可能拼写能力很差,因此同义词列表可能难以维护。
如果您使用 Levenshtein 距离,那么我建议您按单词进行。对于用户输入中的每个单词,计算字段中最接近的单词name
。然后将它们加在一起以获得最佳匹配。
在您的示例中,您将进行以下比较:
- levenshtein('剪刀','电动')
- levenshtein('剪刀', '剪刀')
最小值将是第二个。如果用户键入多个单词,例如'electrk scisors'
,那么你会做
- levenshtein('electrk', 'electric') <-- 最小值
- levenshtein('electrk', '剪刀')
- levenshtein('剪刀','电动')
- levenshtein('scisors', 'scissor') <-- 最小值
这可能是一种接近搜索的直观方式。
推荐阅读
- html - 如何让我的网站在放大和缩小时不变形?
- c# - REST 调用从 Oracle 数据库返回空列表
- c# - 无法加载 DLL 'Microsoft.WITDataStore32.dll':找不到指定的模块。(来自 HRESULT 的异常:0x8007007E)
- xslt - XSLT:选择性缩进可能吗?
- python - 如何使用 pygsheets 用数据更新工作表的底行(第一个空行)?
- c++ - 在类 12.exe 中的 0x7B37FF80 (ucrtbased.dll) 处引发异常:0xC0000005:访问冲突读取位置 0x00B64F88。发生了
- sql - 如何从 MS SQL 服务器中的数据库中仅创建所有表的索引脚本?
- java - RecyclerView 内部的 RecyclerView 没有附加适配器
- reactjs - Axios 获取快速会话返回未定义,但 POSTMAN 返回正确数据
- html - 如何从 SQL Server 中的字符串中删除 CSS 样式标签