最近的項目中有個搜索的功能,本來說,搜索簡單做就可以了,直接like百分號就Ok了。但想了想,咱必須做點高大上的東西出來啊,再加上想練習下我並不熟練的存儲過程,所以,決定搞得高大上些。以前做搜索的時候沒有考慮那么多,但畢竟項目的使用者是廣大用戶,為了增加用戶體驗,所以應該提供給用戶最想搜索的結果給用戶,這里就涉及到了排序,而且是按匹配率排序,也可以說是精確度吧。網上找了會也沒找到合適的。所以就自己寫了。
首先說下我的思維原理:第一步,將要搜索的關鍵詞進行分割,單獨進行模糊匹配。例如:“我是中國人”分割成"我","我是","我是中","我是中國",“我是中國人”,分別對這些關鍵詞進行匹配,第二步,將匹配結果分配到對應的字段,然后按最長的關鍵詞進行排序,就得到了我們想要的結果。
分配關鍵詞的邏輯本來也是打算寫到程序代碼中的,然后動態生成sql語句,發送到數據庫進行執行,但之前不知道在哪兒看到的一篇文章,大概意思就是這樣會增加網絡的吞吐量(現在也無從考證了,知道的告訴我一下吧。)。所以就把整個邏輯寫到了存儲過程中。
下面直接上sql代碼
1 create proc [dbo].[sp_Fuzzy_Search] 2 @keyword nvarchar(15),--將關鍵詞限制在15個字。主要出於性能的原因。再者是匹配一個的搜索詞差不多已經可以滿足用戶的搜索需求了。 3 @tablename varchar(20),--要搜索的表明 4 @cellname varchar(20)--要匹配的字段。此處就寫了一個字段,多個字段的匹配不在考慮范圍內。 5 as 6 begin 7 declare @sql nvarchar(500), @num int,@i int,@orderby varchar(200) 8 set @i=0 9 set @num=len(@keyword) 10 set @sql='select id,'+@cellname+' from ( select id, '+@cellname+',' 11 set @orderby='' 12 while @i<@num --循環獲取關鍵詞。此處是從最長的關鍵詞進行循環的,有利於排序的處理。 13 begin 14 set @sql+=' case when PATINDEX(''%'+substring(@keyword,1,@num)+'%'','+@cellname+')>0 then 1 else 0 end as t'+convert(varchar,@num)+',' 15 set @orderby+='t'+convert(varchar,@num)+' desc,' 16 set @num-=1 17 18 end 19 --拼接sql語句 20 set @sql=left(@sql,len(@sql)-1)+' from '+@tablename+') as TT where t1>0 order by '+left(@orderby,len(@orderby)-1) 21 --執行拼接好的sql語句。 22 EXEC sp_executesql @sql 23 24 end
測試用數據如下圖:
搜索關鍵詞“中國人”,返回值如下:
大概思路就是這樣的,貌似有點bug,各位看官有好的意見或建議,還請不吝賜教。 謝謝。