4

让我们考虑一下User.Note = 'Version:3.7.21.1'

SELECT * FROM [USER] WHERE CONTAINS(NOTE, '"3.7.2*"')

=> 返回一些东西

SELECT * FROM [USER] WHERE CONTAINS(NOTE, '"3.7*"')

=>什么都不返回

如果User.Note = '版本:3.7.21'

SELECT * FROM [USER] WHERE CONTAINS(NOTE, '"3.7*"')

=> 返回一些东西

如果User.Note = '版本:3.72.21'

SELECT * FROM [USER] WHERE CONTAINS(NOTE, '"3.7*"')

=>什么都不返回

我无法弄清楚它是如何工作的。当我搜索“3.7 *”时,它应该总是返回一些东西。

你知道这背后的逻辑是什么吗?

PS:如果我用字母替换数字,没有问题。

4

2 回答 2

4

我认为您的问题是由分词器与数据中的标点符号交互的不可预测性引起的。全文搜索基于字符串的概念,不包括空格和标点符号。当引擎构建索引时,它会看到句点并以奇怪的方式中断单词。

例如,我用您提供的三个值制作了一个小表格......

VALUES (1,'3.7.21.1'),(2,'3.7.21'),(3,'3.72.21')

现在,当我做你的选择时,我得到了所有四个的结果……但不是我期望的结果。

对我来说,这将返回所有三个值

SELECT * FROM containstext WHERE CONTAINS(secondid, '"3.7.2*"')

这只返回3.7.21

SELECT * FROM containstext WHERE CONTAINS(secondid, '"3.7*"')

所以让我们运行一下,看看全文索引的内容

SELECT * FROM sys.dm_fts_index_keywords(db_id('{databasename}'), object_id('{tablename}'))

对于我的结果(您的结果可能完全不同),我有以下 display_term 值

display_term     document_count
    21              3
    3               3
    3.7.21          1
    7               2
    72              1

所以让我们看看第一个搜索条件'"3.7.2*"' 如果我把它推到sys.dm_fts_parser......

select * from sys.dm_fts_parser('"3.7.2*"', 1033, NULL, 0)

...它向我展示了它正在与比赛中断

3
7
2

但如果我这样做...

select * from sys.dm_fts_parser('"3.7*"', 1033, NULL, 0)

我得到了一个完全匹配的术语3.7,并且sys.dm_fts_index_keywords早些时候告诉我,我只有一个文档/行包含3.7

您可能还会遇到额外的怪异,因为数字 0-9 通常在系统停用词中,并且可以被排除在索引之外,因为它们被认为是无用的。这可能就是当您更改为字母时它起作用的原因。

另外,我知道您已决定替换 LIKE,但 Microsoft建议您在全文索引中仅使用字母数字字符,如果您需要在搜索条件中使用非字母数字字符,则应使用 LIKE。也许将句点更改为一些不会在正常值中使用的字母数字替换?

于 2019-01-15T22:27:21.757 回答
-1

仅当列在全文索引中时,包含才会起作用。如果它没有被索引,你将需要使用如下:

SELECT * FROM [USER] WHERE NOTE like '3.7%' --or '%3.7%

你想使用 CONTAINS 是因为你认为它会更快吗?(通常是)

Microsoft 文档列出了您可以格式化和使用 CONTAINS 的所有方式(11 个示例)

这是关于包含的 Microsoft 文档

于 2019-01-15T20:33:48.383 回答