【问题标题】:T-SQL CONTAINS with numbers and dots (.)T-SQL 包含数字和点 (.)
【发布时间】:2019-06-09 20:06:56
【问题描述】:

让我们考虑 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 = 'Version:3.7.21'

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

=> 返回一些东西

如果 User.Note = 'Version:3.72.21'

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

=> 返回

我不知道它是如何工作的。当我搜索“3.7 *”时,它应该总是返回一些东西。

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

PS:如果我把数字换成字母就没有问题了。

【问题讨论】:

  • 你可以使用 like '%3.7.2%' 而不是 contains
  • 谢谢,但我想用“CONTAINS”
  • 您的数据中是否有实际的双引号?
  • 不,但我必须在双引号中加上 * docs.microsoft.com/en-us/sql/t-sql/queries/…
  • 如果您希望经常处理版本号,那么您可能需要添加一个带有“规范化”版本号的列,该版本号将正确排序(“0001.0005.0100.0095”,这样您就找不到"10" This 问题适用。

标签: sql sql-server tsql full-text-search contains


【解决方案1】:

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

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

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.7sys.dm_fts_index_keywords 早些时候告诉我,我只有一个包含 3.7 的文档/行

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

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

【讨论】:

  • 非常感谢您的解释和建议!搜索值“3.7”是一个示例,但我们可以有多个搜索值,例如 SELECT * FROM [USER] WHERE CONTAINS(Note, '"3.7* AND "vers*"" AND "test*"') 我认为将句点更改为一些字母数字字符可能是一种解决方案。我只是尝试替换“。”通过我的数据中的“%2e%”,所以我的查询是SELECT * FROM [USER] WHERE CONTAINS(Note, '"3%2e%7*"'),返回结果。
【解决方案2】:

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

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

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

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

Here is the Microsoft doc on CONTAINS

【讨论】:

  • 是的,我们决定将 LIKE 替换为 CONTAINS 以提高性能。该列在全文索引中。该运算符适用于其他搜索值,但不适用于这种特定情况......问题是:为什么“CONTAINS”不会根据数据返回相同的结果(参见我的示例)?
  • @CelineR 下一次,也许将这些内容包含在您的原始帖子中 -> “该列在全文索引中。该运算符适用于其他搜索值,但不适用于这种特定情况”跨度>
  • 最初的帖子确实说有些搜索会返回结果,而另一些则不会。这应该足以直觉全文索引在那里。
猜你喜欢
  • 2018-11-11
  • 2016-05-28
  • 2020-04-17
  • 2022-11-10
  • 1970-01-01
  • 1970-01-01
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多