Mysql 如何找到完全匹配全部或部分输入的字符串
我想写一个查询来搜索一个包含数百万条记录的表,查找一个值,该值完全,并且只从一开始就与搜索字符串或其子字符串最匹配。表现是最重要的 这就像是一个反面:Mysql 如何找到完全匹配全部或部分输入的字符串,mysql,sql,Mysql,Sql,我想写一个查询来搜索一个包含数百万条记录的表,查找一个值,该值完全,并且只从一开始就与搜索字符串或其子字符串最匹配。表现是最重要的 这就像是一个反面: SELECT * FROM table_name WHERE column_name LIKE '$input%' LIMIT 1 例如,我想在下表中搜索foobar。如果foobar不存在,则搜索fooba,直到最后一个字符f,并返回与之完全匹配的行 +------------------+ | column_name | +---
SELECT * FROM table_name WHERE column_name LIKE '$input%' LIMIT 1
例如,我想在下表中搜索foobar。如果foobar不存在,则搜索fooba,直到最后一个字符f,并返回与之完全匹配的行
+------------------+
| column_name |
+------------------+
| foobar |
+------------------+
| fooba |
+------------------+
| foob |
+------------------+
| foo |
+------------------+
| fo |
+------------------+
| foobarrrrr |
+------------------+
| foooooooooooo |
+------------------+
| barfoo |
+------------------+
我认为没有一种真正有效的方法,但是下面的方法可能会满足您的需要 首先,在
t(列名)
上创建索引
然后,将查询构造为:
select t.*
from ((select t.* from table_name where column_name = $input) union all
(select t.* from table_name where column_name = left($input, 1)) union all
(select t.* from table_name where column_name = left($input, 2)) union all
(select t.* from table_name where column_name = left($input, 3)) union all
(select t.* from table_name where column_name = left($input, 4)) union all
. . .
) t
order by length(t.column_name) desc
limit 1;
注:
- 这是在不同长度的
前缀之间循环。您可以使用PHP完成此操作,并在第一次匹配时停止$input
- 比较时应使用
上的索引列\u name
- 这仅限于精确的子字符串匹配(这就是我对问题的解释)
- 我认为没有一种真正有效的方法,但下面的方法可能会满足您的需要
首先,在
t(列名)
上创建索引
然后,将查询构造为:
select t.*
from ((select t.* from table_name where column_name = $input) union all
(select t.* from table_name where column_name = left($input, 1)) union all
(select t.* from table_name where column_name = left($input, 2)) union all
(select t.* from table_name where column_name = left($input, 3)) union all
(select t.* from table_name where column_name = left($input, 4)) union all
. . .
) t
order by length(t.column_name) desc
limit 1;
注:
- 这是在不同长度的
前缀之间循环。您可以使用PHP完成此操作,并在第一次匹配时停止$input
- 比较时应使用
上的索引列\u name
- 这仅限于精确的子字符串匹配(这就是我对问题的解释)
SELECT column_name
FROM table_name
WHERE 'foobar' LIKE CONCAT(column_name, '%')
ORDER BY LENGTH(column_name) DESC
LIMIT 1
请注意,如果表很大,这将很慢,因为我认为它不能使用索引。如果这是一个问题,那么动态地构建查询会更好。您可以使用列值动态地构建类似于的模式
SELECT column_name
FROM table_name
WHERE 'foobar' LIKE CONCAT(column_name, '%')
ORDER BY LENGTH(column_name) DESC
LIMIT 1
请注意,如果表很大,这将很慢,因为我认为它不能使用索引。如果这是一个问题,动态构建查询会更好。如果我在这个表中搜索
fred
,您会得到什么结果?以f
开头的所有记录?(只是想理解一下你的逻辑,因为它有点不同寻常)。你会在你的例子中返回什么?是的,您将得到f
作为结果更好的方法是使用基于全文的搜索-它有很多有趣的特性我研究了全文匹配,但找不到最合适的方法。如果我在这个表中搜索fred
,您会得到什么结果?以f
开头的所有记录?(只是想了解一下你的逻辑,因为它有点与众不同)。你会在你的示例中返回什么?是的,你会得到f
,结果更好的方法是使用基于全文的搜索-它有很多有趣的特性我研究了全文匹配,但找不到最合适的方法。谢谢你的回答。我希望MySQL中能有一个方法。我想我会在php中使用do…while
,并在php中将字符串的长度减少1,然后在我的表中搜索该子字符串。这可能对长输入字符串的性能不好。您可以使用(@input,LEFT(@input,1),LEFT(@input,2),…)中的列名称来代替union(
@Barmar。我关心的是,这是否总是在列\u name
上使用索引。在这种情况下,MySQL可能会对索引非常挑剔。我认为MySQL通常非常擅长使用的索引,其中列名位于(列表)
中。它容易出错的地方是()中的列名称所在的
@Barmar。我认为在某种程度上,它更喜欢对列表进行排序,并对列表进行二进制搜索。列表可能必须比本例中的典型字符串长一点。谢谢您的回答。我希望MySQL中能有一个方法。我想我会在php中使用do…while
,并在php中将字符串的长度减少1,然后在我的表中搜索该子字符串。这可能对长输入字符串的性能不好。您可以使用(@input,LEFT(@input,1),LEFT(@input,2),…)中的列名称来代替union(
@Barmar。我关心的是,这是否总是在列\u name
上使用索引。在这种情况下,MySQL可能会对索引非常挑剔。我认为MySQL通常非常擅长使用的索引,其中列名位于(列表)
中。它容易出错的地方是()中的列名称所在的
@Barmar。我认为在某种程度上,它更喜欢对列表进行排序,并对列表进行二进制搜索。列表可能必须比本例中的典型字符串长一点。