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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM