前兩篇博客:
?
??????? ?SQL LIKE語句多條件貪婪匹配算法
???????? SQL LIKE語句多條件貪婪加權匹配算法(改進版)
?
???????? 為了更好的擴充本算法的適用范圍,特加入 必要關鍵詞指定功能 。
???????? 在實際應用中,很可能希望匹配的時候必須出現某個詞,否則就是沒有意義的匹配。
???????? 說到這,讀者可能覺得這些需求小題大做,在程序中用正則表達式很容易實現,再次重申,現在的矛盾是我們不能把記錄返回到程序中處理,因為涉及到大數據量,必須考慮服務器承受能力、并發訪問數量、網絡傳輸能力、程序處理能力等諸多因素。在服務器端盡量縮小數據范圍,減少數據傳輸量,無疑是最佳選擇。
???????? 這個版本加入的新特性即必要關鍵詞指定,同樣拿“如何在CSDN網站注冊用戶”這句話來說,“CSDN”這個詞可以認為是必要詞,因為它是前提,試想你在搜索“如何在CSDN網站注冊用戶”時,卻出現了“如何在網易注冊用戶”,顯然是毫無意義的結果。
???????? 事實亦如此,地球人也是這么做的,在百度搜“如何在CSDN網站注冊用戶”,把結果從第一頁翻到最后一頁,可以發現每一個結果中都可以找到“CSDN”字眼。
???????? 其實,大多數情況下,通過貪婪加權匹配,已經可以實現非常重要的詞“必然”出現,但有時候需要做一個保證,讓結果更加合理。
?
SQLLIKE語句多條件貪婪加權匹配(新增必要詞功能):
GO CREATE function Get_StrArrayLength ( @str varchar(1024), --要分割的字符串 @split varchar(10) --分隔符號 ) returns int as begin declare @location int declare @start int declare @length int set @str=ltrim(rtrim(@str)) set @location=charindex(@split,@str) set @length=1 while @location<>0 begin set @start=@location+1 set @location=charindex(@split,@str,@start) set @length=@length+1 end return @length end GO CREATE function Get_StrArrayStrOfIndex ( @str varchar(1024), --要分割的字符串 @split varchar(10), --分隔符號 @index int --取第幾個元素 ) returns varchar(1024) as begin declare @location int declare @start int declare @next int declare @seed int set @str=ltrim(rtrim(@str)) set @start=1 set @next=1 set @seed=len(@split) set @location=charindex(@split,@str) while @location<>0 and @index>@next begin set @start=@location+@seed set @location=charindex(@split,@str,@start) set @next=@next+1 end if @location =0 select @location =len(@str)+1 --這兒存在兩種情況:1、字符串不存在分隔符號 2、字符串中存在分隔符號,跳出while循環后,@location為0,那默認為字符串后邊有一個分隔符號。 return substring(@str,@start,@location-@start) end GO CREATE PROCEDURE proc_Common_SuperLike --要查詢的表的主鍵字段名稱 @primaryKeyName varchar(999), --要查詢的表名 @talbeName varchar(999), --要查詢的表的字段名稱,即內容所在的字段 @contentFieldName varchar(999), --查詢記錄的個數(TOP *),匹配的個數越多,排名越靠前 @selectNumber varchar(999), --匹配字符分隔標記 @splitString varchar(999), --匹配字符組合字符串 @words varchar(999) AS declare @sqlFirst varchar(999) declare @sqlCenter varchar(999) declare @sqlLast varchar(999) declare @next int declare @arrayLength int declare @newWords varchar(999) declare @newTable varchar(999) BEGIN set @newTable=@talbeName set @newWords=@words set @next=dbo.Get_StrArrayLength(@words,'[') --判斷是否有必要詞 if @next>1 begin set @newTable='' --構造必要表sql語句 while @next>1 begin set @newTable=@newTable+@contentFieldName+' like ''%'+dbo.Get_StrArrayStrOfIndex(dbo.Get_StrArrayStrOfIndex(@words,'[',@next),']',1)+'%'' AND ' set @next=@next-1 end set @newTable=left(@newTable,(len(@newTable)-4)) --構造臨時表 set @newTable='SELECT * into ##tempTable FROM '+ @talbeName + ' WHERE ' + @newTable execute(@newTable) --指定臨時表 set @newTable='##tempTable' --去掉關鍵詞組中的必要詞標記 set @newWords=REPLACE(REPLACE(@words,'[',''),']','') end set @sqlCenter='' set @next=1 set @arrayLength=dbo.Get_StrArrayLength(@newWords,@splitString) while @next<=@arrayLength begin --構造sql查詢條件(中間部分) set @sqlCenter = @sqlCenter+'SELECT '+@primaryKeyName+','+CONVERT(varchar(999),@arrayLength-@next+1)+' AS wordPower FROM '+@newTable+' WHERE '+@contentFieldName+' like ''%'+dbo.Get_StrArrayStrOfIndex(@newWords,@splitString,@next)+'%'' UNION ALL ' set @next=@next+1 end --處理sql語句中間部分,去除最后無用語句 set @sqlCenter=left(@sqlCenter,(len(@sqlCenter)-10)) --構造sql語句開頭部分 set @sqlFirst='SELECT TOP '+@selectNumber+' '+@primaryKeyName+',COUNT(*)+SUM(wordPower) AS finalPower FROM (' --構造sql語句結尾部分 set @sqlLast=') AS t_Temp GROUP BY '+@primaryKeyName+' ORDER BY finalPower DESC' --拼接出完整sql語句,并執行 Execute(@sqlFirst+@sqlCenter+@sqlLast) --判斷臨時表是否存在,存在則刪除,一定要刪除! if OBJECT_ID('tempDb..##tempTable') is not null begin drop table ##tempTable end END
調用方法基本不變(參數個數未變):
?
???????? execute proc_Common_SuperLike'id','t_test','content','20','|','[i]|o|c'
?
新特性說明:
?
???????? l? 定義: 把必須要出現的關鍵詞用方括號[]括起來。例如[i]|o|c,則i在結果中必須出現。
???????? l? 說明: 假如需要匹配a、b、c三個關鍵詞,重要性:a>b>c,那么可以這樣寫:a|b|c,這樣已經保證a、b、c的權重依次降低,貪婪加權的算法基本可以保證:盡可能多的去匹配、盡可能匹配包含a的記錄。但是某些時候為了提高準確性,要求結果中必須出現a,那么可以這樣寫:[a]|b|c。同理,必須出現a、b可以這樣寫:[a]|[b]|c。
???????? l? 其他: 此次更新加入了臨時表技術,保證必要關鍵詞指定效率。
?
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
