前兩篇博客:
?
??????? ?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元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

