• SQL LIKE语句多条件贪婪加权匹配(新增必要词指定)


    前两篇博客:

     

            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'

     

    新特性说明:

     

             定义:把必须要出现的关键词用方括号[]括起来。例如[i]|o|c,则i在结果中必须出现。

             说明:假如需要匹配a、b、c三个关键词,重要性:a>b>c,那么可以这样写:a|b|c,这样已经保证a、b、c的权重依次降低,贪婪加权的算法基本可以保证:尽可能多的去匹配、尽可能匹配包含a的记录。但是某些时候为了提高准确性,要求结果中必须出现a,那么可以这样写:[a]|b|c。同理,必须出现a、b可以这样写:[a]|[b]|c。

             其他:此次更新加入了临时表技术,保证必要关键词指定效率。

     

     

    原创算法,欢迎转载,可用于任何用途,注明出处即可!


  • 相关阅读:
    Swift 可选项 Optional
    Swift 枚举的用法
    Swift 函数
    Swift 流程控制
    iPhone 相册取出视频宽高分辨率是相反的 解决方案
    Mac 下GitHub 访问慢解决方案
    Ipa 脱壳工具 Clutch dumpdecrypted 使用
    逆向 make 打包错误解决方案 make: *** [internal-package] Error 2
    删除 $PATH 路径下多余的文件地址
    Reveal 破解 无限试用
  • 原文地址:https://www.cnblogs.com/iyangyuan/p/2801806.html
Copyright © 2020-2023  润新知