亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

SQL LIKE語句多條件貪婪匹配算法

系統 2815 0

???????? 在CMS開發中,經常會有類似這樣的需求:

???????? 提問——回答模式,最經典的例子就是百度提問。

???????? 提問者提出問題,由其他人回答,其他人可以是用戶,也可以是服務商。

???????? 在這個模式中,如何充分利用歷史數據是最關鍵的技術。很多時候,由于客戶不擅長使用搜索功能,一上來就提問,而這些問題往往早已經有近乎完美的答案,但沒有充分利用。這樣一來,不僅加大了勞動量,又增加了數據冗余。

???????? 如果在提問的時候能充分調動歷史數據,提交問題之前先看看歷史問題能不能解決客戶疑問,解決了,最好不過,解決不了,再提交。百度提問就是采用的這種方案:


SQL LIKE語句多條件貪婪匹配算法


???????? 模式固然好,可怎么實現就有些困難了,畢竟這是百度作為搜索引擎的看家本領。

???????? 從上圖可以看出“CSDN網站如何注冊用戶”這句話被拆成了N個詞,然后分開去數據庫中匹配,為什么?因為直接去匹配“CSDN網站如何注冊用戶”這句話,漢語博大精深,稍微變動一下:“如何在CSDN網站注冊用戶”,意思完全一樣,但直接匹配絕對匹配不到!

???????? 因此,我們需要把一句話拆分成詞組,這個在網上有現成的組件,比如“庖丁解牛”等,它們大多數是免費開源的。拆成詞組之后,應該還要有一個關鍵詞篩選詞庫,用這個詞庫確定出有效的詞組,比如上圖中,“CSDN”、“注冊”、“用戶”是有效的,而“網站”顯然沒有匹配,因為它在這句話中沒有實際意義。

???????? 有點跑題了,拆詞、選詞不是本文的重點,但卻是本文的前提。拿到關鍵詞之后,怎么去數據庫中匹配呢?

???????? 大家都知道T-SQL中的LIKE語句,通過類似LIKE “%abc%”這樣的語法,可以進行模糊匹配,但是它僅僅能進行一次模糊匹配。舉個例子:

???????? 假如我們確定了a,b,c三個關鍵詞,要查找的記錄當然是匹配的越多越好,于是可以這樣寫:LIKE “%a%b%c%”,這樣匹配出的就是包含a,b,c三個關鍵詞的記錄,但是如果根本沒有包含這三個關鍵詞的記錄,最多只有包含兩個的,甚至是只包含一個,那么如何寫LIKE語句呢?這樣LIKE “%a%b%”?這樣LIKE “%a%c%”?這樣LIKE “%b%c%”?這樣LIKE “%a%”?這樣LIKE “%b%”?這樣LIKE “%c%”?

???????? 顯然,需要判斷的情況太多,簡單的LIKE語句已經無法滿足需求。需要注意的是,千萬不要試圖選出范范的記錄,返回到程序中去處理,在程序中處理雖然簡單,但是范范的記錄,在一個中型系統中,往往能達到千萬級別,這么大的數據量,從數據庫返回到程序,無疑會給服務器造成相當大的壓力。

???????? 經過探索,本小菜總結了一個比較簡單的方法,暫且稱為“LIKE語句多條件貪婪匹配算法”。

???????? 算法思想: 先用LIKE選出每一組符合一個條件的記錄,只選擇表的主鍵。然后把這些記錄合并在一起,通過主鍵分組、統計數量,數量最多的,也就是匹配最多的,最后根據數量降序排序,越靠上的記錄,匹配的越多。選出匹配的多的記錄主鍵字段,再根據主鍵去表中選出內容即可。

???????? 為了方便大家使用,已經把算法封裝成存儲過程(直接把下邊代碼在查詢分析器中執行即可)。

存儲過程(函數)如下:

    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)
BEGIN
	set @sqlCenter=''
	declare @next int  
	set @next=1
	while @next<=dbo.Get_StrArrayLength(@words,@splitString)
	begin
		--構造sql查詢條件(中間部分)
		set @sqlCenter = @sqlCenter+'SELECT '+@primaryKeyName+' FROM '+@talbeName+' WHERE '+@contentFieldName+' like ''%'+dbo.Get_StrArrayStrOfIndex(@words,@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(*) AS showCout FROM ('
	--構造sql語句結尾部分
	set @sqlLast=') AS t_Temp GROUP BY '+@primaryKeyName+' ORDER BY showCout DESC'
	--拼接出完整sql語句,并執行
	execute(@sqlFirst+@sqlCenter+@sqlLast)
END
  

調用示例:

    executeproc_Common_SuperLike 'id','t_test','content','20','|','i|o|c'
  

???????? id表的主鍵字段名稱。

???????? t_test表名。

???????? content匹配內容字段名稱。

???????? 20選出20個記錄(從頂至下匹配度越來越低)。

???????? |關鍵字的分隔符號。

???????? i|o|c一共有i,o,c三個關鍵字,通過|分隔。

?

???????? 注意這個存儲過程選出來的是匹配度高的記錄的主鍵,還需要根據主鍵去表中查一下,查詢出需要的內容(問題名稱)。

???????? 有問題歡迎和我交流,原創算法,可用于任何場合,注明出處即可。

SQL LIKE語句多條件貪婪匹配算法


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美日韩另类综合 | 日日摸夜夜爽日日放碰 | 老子影院午夜伦手机不四虎 | 黄片毛片| 天天操天天草 | 青青99| 曰本还a大片免费无播放器 曰本黄色录像 | 天天做天天爱天天一爽一毛片 | 亚洲狠狠成人综合网 | 一区二区三区毛片免费 | 中国一级全黄的免费观看 | 免费一级片 | 国产日韩欧美在线观看免费视频 | 黄 色 三 级 网站 | 精品久久中文字幕 | 亚洲免费视 | 女bbbbxxxx毛片视频丶 | 亚洲成人免费观看 | 久久频这里精品99香蕉久网址 | 国产只有精品 | 欧美xxxx成人免费网站 | 久久精品国产一区二区三区不卡 | 色天使色婷婷在线影院亚洲 | 欧美成人h版影片在线观看 欧美成人h精品网站 | 一级毛片网| 国产真实偷乱视频在线观看 | 毛片一级免费 | 91色综合 | 中文字幕亚洲高清综合 | 国产精品一二区 | 亚洲和欧美毛片久久久久 | 99视频精品全部在线播放 | 99久久久久久久 | 欧美亚洲动漫 | 乱色专区 | 精品日本亚洲一区二区三区 | 51国产福利视频在线观看 | 国产精品国色综合久久 | riav久久中文一区二区 | 老妇综合久久香蕉蜜桃 | 狠狠狠地在啪线香蕉 |