最近在工作中有这样一个需求,匹配String str1 = 'a|b|c'和String str2 = 'e|a|c|d',以'|'为分隔符分割,分割后str1 = {a,b,c} str2={e,a,c,d},若str1和str2分割后有重复的项则返回为1,否则返回0
很多熟悉sql的人都知道,匹配字符串有个like函数,但是like函数匹配的字段必须是完全相同的
例如:select 'a|b|c' like '%a|b%' 是如果第一个字符串含有第二个字符串的话返回为1,此语句的返回值为1
但是 select 'a|b|c' like '%a|c%' 返回为0,也就是第一个字符串没有完全匹配第二个字符串
如果我们想要以'|'为分隔符,如果第一个字符串与第二个字符串有相同的部分,就返回为1,反之返回为0的话单单用一条like语句就无法实现了,这个时候的实现思想可以是把第二个字符串用'|'分隔开之后,意义去分隔开的数据,然后与第一个字符串进行like查询,也就是将
select 'a|b|c' like '%a|c%'
拆分为
select 'a|b|c' like '%a%' 和select 'a|b|c' like '%c%'
拆分后查询若有一个为1,就代表有相同的选项,就返回为1;拆分后的查询都为0,就代表无匹配的项,就返回为1
说到这里,我们就很自然而然的想到了,这个思想可以用函数实现,函数如下:
(这个函数是同事写出来的,不知是否有参考网上代码,因此也不知源码地址,如有人知道,可以在评论里指出)
set @tmp = a;
set @result = 0;
set @token = '';
set @ind = 0;
while (@tmp <> '') DO
-- |的索引
set @ind = position('|' in @tmp);
if( @ind <= 0) THEN
set @token = @tmp;
set @result = @token REGEXP b;
set @tmp = '';
ELSE
set @token = left(@tmp,@ind - 1);
set @result = @token REGEXP b;
if(@result > 0) THEN
set @tmp = '';
ELSE
-- 修改原始字符串
set @tmp = right(@tmp,LENGTH(@tmp) - @ind);
END IF;
end IF;
END WHILE;
return @result;
end
现在利用上面的函数再执行一下
select getLike('a|b|c','a|b')
返回结果为1
起初这个函数是能够正常执行的,但是随着运用的次数增多,函数显示显示出了这个函数的隐藏bug,就是不能匹配中文,select getLike('技术|运营|产品','%技术|运营%'),执行这句代码数据库就会卡死,原因是getLike函数中的REGEXP不支持中文
因此,上面的函数改成了下面这样
<pre name="code" class="sql">BEGIN
set @tmp = a;
set @result = 0;
set @token = '';
set @ind = 0;
while (@tmp <> '') DO
-- |的索引
set @ind = position('|' in @tmp);
if( @ind <= 0) THEN
set @token = @tmp;
set @result = b like concat('%',@token,'%');
set @tmp = '';
ELSE
set @token = SUBSTRING(@tmp FROM 1 for @ind - 1);
set @result = b like concat('%',@token,'%');
if(@result > 0) THEN
set @tmp = '';
ELSE
-- 修改原始字符串
set @tmp = SUBSTRING(@tmp FROM @ind + 1);
END IF;
end IF;
END WHILE;
return @result;
end
现在再试一下
select getLikeNew('技术|运营|产品','技术|运营')
返回就是1了
如果有人有更好的方法可以写下来一起分享哦~哪里写的不完全正确也欢迎指出~~