SQL Server 全文索引查询(Full-text index)之二

SQLServer 全文检索(full-text)语法 里已经掌握了基本的contains语法和freetext语法的用法,但是面对一些复杂的操作,基本的包含语法是不够用的,如果我们想要查询含有“世界”或“末日”的所有字符串集合,那么无论是contains([column],'世界末日')或者freetext([column],'世界末日')都不能很好的工作,当然contains本身是可以含有条件的,因此有两个解决方案。

第一个就是传统的where多条件查询,加上两个contains语句,然后用or连接

select [Column] as [result] from Sample where contains([Column],'世界') or contains([Column],'末日')

现在,介绍如何直接使用一个contains语句实现多条件查询,语法的结构如下

1 contains([Column],'"keyword1" and "keyword2" and ......')
2 contains([Column],'"keyword1" or "keyword2" or ......')
3 contains([Column],'("keyword1" or "keyword2") and ......')

其实也就是在两个单引号内实现多条件,and表示交集,or表示并集,我们运行如下T-SQL

select [Column] as [result] from Sample where contains([Column],'"世界" or "末日"')

两次查询均返回了1820条记录,可以看到,排在前面的记录两者是不一样的,因此这两种方式的查询在底层的执行方式是不一样的,往往把条件都放在一个contains里会有更高的效率。

要注意的是,freetext本身就是模糊查询了,它不能再带有条件,如果想尝试在freetext里加入条件语句是没有意义的,不会返回任何结果。

现在总结一下contains和freetext,可以看到,使用这两个查询方法很简单,效率较高,但是它们一个很大的不足:

contains和freetext不会限定返回结果的数量,而是将满足条件的全部返回,这会带来两个比较重要的问题,

  1.我们会得到很多无用的结果,同时如果返回结果过多,也会极大影响查询效率

  2.返回的结果是无序的,并没有按照预想的如“相似程度”进行排序,导致最好的查询结果往往不再最前面

为了克服这样的问题,就可以使用containstable和freetexttable语法,这两个查询方法可以限定返回结果的数量,同时能赋予一个rank函数(相似度函数)返回rank最大的n个结果,这就是著名的top_n_by_rank argument

使用containstable和top_n_by_rank需要使用表的内连接操作,内连接也称为等同连接,返回的结果集是两个表中所有相匹配的数据,用on进行连接。我们让containstable返回的结果集作为一个表k,该表拥有两个字段,一个是key字段,一个是rank字段,在查询时需要将key字段与查询字段中的一个主键(唯一字段)相进行连接,如下

1 SELECT [Column] as [result] From wiki --查询Column字段的记录,该字段是唯一字段,并且已建立全文索引
2 inner join --内连接
3 containstable(Sample,[Column],'"世界" or "末日"',500) as k --含有“世界”和“末日”的前500条记录作为表k
4 on wiki.fs_wiki_title = k.[key] --连接条件
5 ORDER BY k.RANK DESC --按照k的rank降序排列,即相似度越高的越靠前

现在的查询时间已经大大减少,因为我们只返回500条记录,并且这些记录都是与给定的“世界”或“末日”非常接近的。

下面,我们可以进行一些更加高级的查询,比如在containstable语法里限定条件,这个时候我们要在库里查含有“世界”并且含有“末日”的所有字符串,执行如下T-SQL语句

1 SELECT [Column] as [result] From Sample
2 inner join containstable(Sample,[Column],'"世界" and "末日"',500) as k 
3 on Sample.Column = k.[key]
4 ORDER BY k.RANK DESC

继续,我们再限定查找字符串长度小于等于6,执行如下T-SQL语句

1 SELECT [Column] as [result] From Sample
2 inner join containstable(Sample,[Column],'"世界" and "末日"',500) as k 
3 on Sample.Column = k.[key]
4 where len([Column])<=6
5 ORDER BY k.RANK DESC

这个时候返回结果就很精确了,因此我们通过containstable能够非常灵活的进行查询设计并且对返回结果按相似度排序。freetexttable的用法和containstable用法类似,因此这里不再讲解。

RANK()函数详细资料参考:https://www.cnblogs.com/xiaoyue1606bj/p/11021751.html

其他查询详细数据情况可参考https://www.cnblogs.com/kissdodog/p/3376346.html

                https://wenku.baidu.com/view/2160f41fff00bed5b9f31dc5.html

    https://social.msdn.microsoft.com/Forums/zh-CN/42f48bfe-0095-4e1d-a0f8-5127de3ff898/2084025991268163203465292contains?forum=sqlserverzhchs

posted @ 2019-06-12 11:52  奋进的小土豆  阅读(2023)  评论(0编辑  收藏  举报