匹配没有 space 和标点符号 MySQL 的字符串
Matching strings without space and punctuation in MySQL
我正在处理一个我认为应该非常直观的查询,但不知何故,我在实现它时遇到了一些问题。我想我想要实现的是匹配存储在 MySQL DB 中的字符串,不带 space 和标点符号(其他创造性方法非常受欢迎)。同时,我希望查询以变音符号不敏感的方式处理 Unicode 字符(因此像 REGEXP 这样的选项有点不走运)。最后一个条件是我在 MySQL 5.5 上使用 InnoDB 引擎,因此不支持全文索引(但如果它有助于解决这个问题,我愿意升级到 5.6/5.7)。
考虑这样一个场景,其中来自 John Doe 的字符串 Hello-World 存储在数据库中。我想在给定搜索字符串 HelloWorld 或 JohnDoe 时找到它。更一般地说,DB 中的字符串可以包含方括号、下划线和任何其他标点符号(不限于 ASCII,但现在可以妥协),而搜索字符串可以是单词的组合,中间有或没有任何分隔符。到目前为止,我最接近的是菊花链 REPLACE 函数以获得已知标点符号列表,如下所示:
SELECT text FROM table WHERE REPLACE(REPLACE(text, '-', ''), ' ', '') LIKE '%JohnDoe%'
我的问题是:
- 有没有更好的方法来代替上面的菊花链?
- 如果这是唯一的解决方案,当我链接一百个或更多 REPLACE 函数时,性能会受到怎样的影响?
在此先感谢您的帮助。
我不知道你的搜索必须有多严格,但你可以尝试从中删除所有非字母数字字符,这样你最终会得到一个像 "HelloWorldfromJohnDoe" 这样的匹配字符串相反。
看看这个答案:How to remove all non-alpha numeric characters from a string?
您可能需要对其进行一些更改以使其符合您的目的。我将它从 CHAR(32) 更改为 CHAR(255) 以确保我可以获得该列,但您可能想要考虑完全更改函数以更精确地适合您的数据。
那你是这样的:
SELECT *
FROM testing
WHERE alphanum(test) LIKE CONCAT('%', alphanum('John Doe'), '%')
应该会给你一个打击。
我完全没有理解你问题的重点。您似乎有字符串:
Hello-World from John Doe
如果要在搜索字符串为JohnDoe
或John Doe
时找到这个,那么只需要替换空格:
where replace(text, ' ') like concat('%', 'JohnDoe', '%')
如果您想要一个同时包含 "John" 和 "Doe" 的字符串,那么:
where replace(text, ' ') like concat('%', 'John%Doe', '%')
我不明白为什么需要 100 个嵌套 replace()
。
方法一
我会在包含 "hashed" 版本的名称的架构上有另一列,例如,假设您有用户:
John Doe The Great
这个名字哈希到
johndoethegreat
散列函数的编码方式使得以下所有字符串:
John_Doe_THE_great
John Doe The GREAT
John.Doe.The.Great
johnDOE___theGreat
john Doe the great
___john____DOE____THE____great
散列到相同的值
johndoethegreat
编写这样的函数很简单。通过这种方式,您可以获得用户输入,对其进行哈希处理,然后将其与数据库中的哈希列进行比较
名称如:
Jon Doe
John Doo
当然找不到
方法二
使用 MySQL 中内置的 FULLTEXT
搜索功能,按得分对结果排序并选择第一个非零条目
http://blog.oneiroi.co.uk/mysql/php/mysql-full-text-search-with-percentage-scoring/
我正在处理一个我认为应该非常直观的查询,但不知何故,我在实现它时遇到了一些问题。我想我想要实现的是匹配存储在 MySQL DB 中的字符串,不带 space 和标点符号(其他创造性方法非常受欢迎)。同时,我希望查询以变音符号不敏感的方式处理 Unicode 字符(因此像 REGEXP 这样的选项有点不走运)。最后一个条件是我在 MySQL 5.5 上使用 InnoDB 引擎,因此不支持全文索引(但如果它有助于解决这个问题,我愿意升级到 5.6/5.7)。
考虑这样一个场景,其中来自 John Doe 的字符串 Hello-World 存储在数据库中。我想在给定搜索字符串 HelloWorld 或 JohnDoe 时找到它。更一般地说,DB 中的字符串可以包含方括号、下划线和任何其他标点符号(不限于 ASCII,但现在可以妥协),而搜索字符串可以是单词的组合,中间有或没有任何分隔符。到目前为止,我最接近的是菊花链 REPLACE 函数以获得已知标点符号列表,如下所示:
SELECT text FROM table WHERE REPLACE(REPLACE(text, '-', ''), ' ', '') LIKE '%JohnDoe%'
我的问题是:
- 有没有更好的方法来代替上面的菊花链?
- 如果这是唯一的解决方案,当我链接一百个或更多 REPLACE 函数时,性能会受到怎样的影响?
在此先感谢您的帮助。
我不知道你的搜索必须有多严格,但你可以尝试从中删除所有非字母数字字符,这样你最终会得到一个像 "HelloWorldfromJohnDoe" 这样的匹配字符串相反。
看看这个答案:How to remove all non-alpha numeric characters from a string?
您可能需要对其进行一些更改以使其符合您的目的。我将它从 CHAR(32) 更改为 CHAR(255) 以确保我可以获得该列,但您可能想要考虑完全更改函数以更精确地适合您的数据。
那你是这样的:
SELECT *
FROM testing
WHERE alphanum(test) LIKE CONCAT('%', alphanum('John Doe'), '%')
应该会给你一个打击。
我完全没有理解你问题的重点。您似乎有字符串:
Hello-World from John Doe
如果要在搜索字符串为JohnDoe
或John Doe
时找到这个,那么只需要替换空格:
where replace(text, ' ') like concat('%', 'JohnDoe', '%')
如果您想要一个同时包含 "John" 和 "Doe" 的字符串,那么:
where replace(text, ' ') like concat('%', 'John%Doe', '%')
我不明白为什么需要 100 个嵌套 replace()
。
方法一
我会在包含 "hashed" 版本的名称的架构上有另一列,例如,假设您有用户:
John Doe The Great
这个名字哈希到
johndoethegreat
散列函数的编码方式使得以下所有字符串:
John_Doe_THE_great
John Doe The GREAT
John.Doe.The.Great
johnDOE___theGreat
john Doe the great
___john____DOE____THE____great
散列到相同的值
johndoethegreat
编写这样的函数很简单。通过这种方式,您可以获得用户输入,对其进行哈希处理,然后将其与数据库中的哈希列进行比较
名称如:
Jon Doe
John Doo
当然找不到
方法二
使用 MySQL 中内置的 FULLTEXT
搜索功能,按得分对结果排序并选择第一个非零条目
http://blog.oneiroi.co.uk/mysql/php/mysql-full-text-search-with-percentage-scoring/