求ID对应DAYS字段的连续天数、连续次数、累计天数
#天数只有本月内,不跨月,不跨年
#连续天数取最后一次连续天数
#连续次数取连续3天算一次,每增加连续1天加1,如果连续天数为4天,连续次数就是1+1,连续天数为5天,连续次数就是1+2
#如果连续天数被打断,则连续打断,重新开始计算连续异常次数
这个问题要分两步来考虑:
第一步:将日期字符串切分开,并和对应的ID另存为一张表。
第二步:从第一步得到表中,查询各ID的对应DAYS字段的连续天数、连续次数、累计天数。
原始表的数据如下图所示:
第一步:
1、建表,用于存放处理好的字期和对应ID
create table days_tb(
ID varchar(5),
DAYS date
);
2、定义存储过程,用于将字符串日期转化为行的形式,并和对应ID存入表中
delimiter //
create procedure sub_str(id varchar(5),days_item varchar(100))
begin
insert into days_tb(id,days) SELECT id,SUBSTRING_INDEX(SUBSTRING_INDEX(days_item,',',help_topic_id+1),',',-1) AS num
FROM mysql.help_topic
WHERE help_topic_id < LENGTH(days_item)-LENGTH(REPLACE(days_item,',',''))+1;
end //
delimiter ;
3、定义存储过程,利用游标,将所有的记录都进行第2步的处理
delimiter //
create procedure days_pro()
begin
declare done int default 0;
declare days_item varchar(100);
declare id_item varchar(5);
declare days_cursor cursor for select ID,DAYS from item_tb;
declare continue handler for not FOUND set done = 1; /*done = true;亦可*/
open days_cursor;
repeat
fetch days_cursor into id_item,days_item;
if not done then
call sub_str(id_item,days_item);
end if;
until done end repeat;
close days_cursor;
end //
delimiter ;
处理完成后,此时原始表中的数据被转换到新表days_tb中,格式如下:
第二步:
从新表days_tb中查询各ID的对应DAYS字段的连续天数、连续次数、累计天数。
select t5.ID,t5.days1,if(t5.days1>=3,t5.days1-2,0) as con_count,t7.cumsum_days from(
select ID,start_date,count(count_day) as days1,sum(t4.count_day) as cum_days from(
select ID,
@start_day:=DAYS as start_date,
@count_day:=
(case
when (@ID:=ID and datediff(DAYS, @end_date)=1) then (@count_day+0)
when (@ID:=ID and datediff(DAYS, @end_date)<1) then (@count_day+0)
else (@count_day+1)
end) as count_day,
@ID:=ID,
@end_date:=DAYS
from (select ID,DAYS from days_tb order by ID) as t2,
(select @ID:='',@start_date:='',@end_date:='',@count_day:=0) as t3) as t4
group by ID,count_day) as t5,
(select ID,max(start_date) as date_max,sum(days1) as cumsum_days from(
select ID,start_date,count(count_day) as days1 from(
select ID,
@start_day:=DAYS as start_date,
@count_day:=
(case
when (@ID:=ID and datediff(DAYS, @end_date)=1) then (@count_day+0)
when (@ID:=ID and datediff(DAYS, @end_date)<1) then (@count_day+0)
else (@count_day+1)
end) as count_day,
@ID:=ID,
@end_date:=DAYS
from (select ID,DAYS from days_tb order by ID) as t2,
(select @ID:='',@start_date:='',@end_date:='',@count_day:=0) as t3) as t4
group by ID,count_day)as t6 group by ID)as t7
where t5.start_date=t7.date_max and t5.ID=t7.ID;
格式有点乱,大概就是这样。
查询结果如下:
你这个比较复杂要用程序或存储过程才能实现
我有思路,不过要认下,连续天数大于等于3天的,连续次数和连续天数是一样的,小于3天的,连续次数是0吗?
如果连续天数被打断,则连续打断,重新开始计算连续异常次数,连续异常次数是?
有个思路就是 group by id; order by id, 然后相邻的天数相减看差值是否为1(连续);
最好做的就是程序查询出数据,程序去处理
您好,我是有问必答小助手,你的问题已经有小伙伴为您解答了问题,您看下是否解决了您的问题,可以追评进行沟通哦~
如果有您比较满意的答案 / 帮您提供解决思路的答案,可以点击【采纳】按钮,给回答的小伙伴一些鼓励哦~~
ps:问答VIP仅需29元,即可享受5次/月 有问必答服务,了解详情>>>https://vip.csdn.net/askvip?utm_source=1146287632
说一下我的思路:先把日期数据行转列,根据id和日期(由大到小)排序,然后根据id和日期减一进行比较是否连续,最后统计各id第一个日期的连续天数再对天数进行处理。