mysql复杂函数_《MYSQL》----字符串的复杂函数,检索的七-天-排-重

博客讲述了在MySQL中处理复杂字符串函数,以解决接口日志排重问题。首先创建了一个函数RemoveTimestampAndSignature,用于从URL中移除时间戳和数字签名参数。然后,通过新建表并计算MD5值来实现接口调用的排重,最后利用时间差不超过7天的条件筛选重复记录。这种方法虽然效率不高,但在当前情况下是有效的解决方案。
摘要由CSDN通过智能技术生成

《MYSQL》----字符串的复杂函数,检索的七-天-排-重

接到了一个新的需求,拿到需求的时候瞬间有点头大,因为实在是有些棘手。

我们这个系统本身是个接口系统,总接口数大概在200个左右。外部会有很多用户在不同的时间拿着不同参数去调我们的这些接口,用户的调集记录会写在数据库的一个日志表里。日志表字段大概有url(带参数),用户id,调用时间,返回结果等等等等。现在的需求是,查询一定时间范围内(12月)里,同一个用户在7天之内调用的接口url和时间。

麻烦的是接口url本身比较复杂。它的长度大约在200-500,里面有几个麻烦的参数:一个是时间戳,时间戳有可能是传递,也有可能是生成的,它铁定不重复。另一个是数字签名,它会根据参数和时间戳通过算法生成,也铁定不重复。所以解决这个问题的第一步,是把url进行处理。去掉这两个铁定不重复的参数。

这个系统还有个让人蛋疼的地方,就是它是两个系统合二为一的。两个系统的时间戳和数字签名参数名称是不一样的,也就是说有四个参数需要判断是否存在+处理。这一步肯定是用函数做。新建函数如下:

CREATE FUNCTION ReplaceUrl (strUrl varchar(800))

RETURNS varchar(800)

BEGIN

DECLARE v_Tmp_1 varchar(800) default '';

DECLARE v_Tmp_2 varchar(800) default '';

DECLARE v_Tmp_3 varchar(800) default '';

DECLARE v_Tmp_4 varchar(800) default '';

SET v_Tmp_1 = if(locate('timeStamp',strUrl)>0,REPLACE(strUrl,SUBSTRING_INDEX(SUBSTRING_INDEX(strUrl,'timeStamp',-1),'&',1),''),strUrl);

SET v_Tmp_2 = if(locate('time_stamp',v_Tmp_1)>0,REPLACE(v_Tmp_1,SUBSTRING_INDEX(SUBSTRING_INDEX(v_Tmp_1,'time_stamp',-1),'&',1),''),v_Tmp_1);

SET v_Tmp_3 = if(locate('access_signature',v_Tmp_2)>0,REPLACE(v_Tmp_2,SUBSTRING_INDEX(SUBSTRING_INDEX(v_Tmp_2,'access_signature',-1),'&',1),''),v_Tmp_2);

SET v_Tmp_4 = if(locate('accessSignature',v_Tmp_3)>0,REPLACE(v_Tmp_3,SUBSTRING_INDEX(SUBSTRING_INDEX(v_Tmp_3,'accessSignature',-1),'&',1),''),v_Tmp_3);

RETURN v_Tmp_4;

END;

MYSQL中if函数使用方法是if(参数1,参数2,参数3),如果参数1正确则执行参数2,不正确执行参数3。这里先判断url是否含有参数A,如果含有则执行替换,不含有则什么都不处理。

替换的逻辑是REPLACE函数,REPLACE(参数1,参数2,参数3),参数1是等待执行的参数,参数2是被替换的字段,参数3是替换为的字段。我们把指定参数替换为空就可以了。

里面还有个参数是SUBSTRING_INDEX——按关键字截取字符串,用法是substring_index(被截取字段,关键字,关键字出现的次数),次数为正是往右数,次数为负是往左数。我们直接把次数设置为-1,也就是参数分隔符&左边的该参数全部被截取就可以了。

连续执行4次之后,url的四个随机生成参数全部被清除,可以执行查重了。

第二步,排重。

难的不是排重,而是排重之后还要加上7天检索的算法。问题可以简化为,有一张表,表里只有3个字段,id,name,time。现在要检索重复的name,还要加上time必须在7天之内,否则就不算重复。

那么答案是:

select t1.* from table_name t1 join table_name t2 on t1.name=t2.name and t1.id!=t2.id

where abs(t1.time-t2.time)<=7

这是一张表当两张表关联查询,虽然我知道会很慢,目前也没有更好的办法能解决这个问题。

那么,这个问题最终的解决语句是,新建函数——将范围内的日志调取出来新建表——把新表处理后的url执行md5——再查重

CREATE FUNCTION ReplaceUrl (strUrl varchar(800))

RETURNS varchar(800)

BEGIN

DECLARE v_Tmp_1 varchar(800) default '';

DECLARE v_Tmp_2 varchar(800) default '';

DECLARE v_Tmp_3 varchar(800) default '';

DECLARE v_Tmp_4 varchar(800) default '';

SET v_Tmp_1 = if(locate('timeStamp',strUrl)>0,REPLACE(strUrl,SUBSTRING_INDEX(SUBSTRING_INDEX(strUrl,'timeStamp',-1),'&',1),''),strUrl);

SET v_Tmp_2 = if(locate('time_stamp',v_Tmp_1)>0,REPLACE(v_Tmp_1,SUBSTRING_INDEX(SUBSTRING_INDEX(v_Tmp_1,'time_stamp',-1),'&',1),''),v_Tmp_1);

SET v_Tmp_3 = if(locate('access_signature',v_Tmp_2)>0,REPLACE(v_Tmp_2,SUBSTRING_INDEX(SUBSTRING_INDEX(v_Tmp_2,'access_signature',-1),'&',1),''),v_Tmp_2);

SET v_Tmp_4 = if(locate('accessSignature',v_Tmp_3)>0,REPLACE(v_Tmp_3,SUBSTRING_INDEX(SUBSTRING_INDEX(v_Tmp_3,'accessSignature',-1),'&',1),''),v_Tmp_3);

RETURN v_Tmp_4;

END;

CREATE TABLE api_table (

SELECT ReplaceUrl(T5)

as temp,T1,DATE(T6) as daytemp,T5,T6

FROM

`v2-api-log`WHERE DATE(t6) BETWEEN '2017-11-24' AND '2017-12-24')

alter table api_table add column md5temp varchar(50);

UPDATE api_table set md5temp = MD5(temp);

ALTER TABLE api_table ADD INDEX tempindex (md5temp);

create table api_repeat(

SELECT

t1.temp,t1.T1,t1.T6

FROM

api_table t1

JOIN api_table t2 ON t1.md5temp = t2.md5temp

AND t1.T1 = t2.T1

AND t1.T6 != t2.T6

WHERE

abs(t1.daytemp - t2.daytemp) <= 7

GROUP BY T6)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值