需求:统计用户在各个月份的活跃(演示一个月的数据),一个用户在同一天会多次活跃,只记做一次
基本sql:
SELECT
token
FROM
sdk_log.hear_beat_log bt
WHERE
bt.create_time >= '2020-09-01'
AND bt.create_time < '2020-10-01'
AND app_id IN ( 'bird_11d_cn_20190524', 'fbbdand2004' )
GROUP BY
token,
DATE_FORMAT( create_time, '%Y-%m-%d' )
结果:全表扫描,查不出来
解决方案:
步骤一:将9月份的token 存入中间表middle_log
CREATE DEFINER=`mtk`@`%` PROCEDURE `temp_heart`(IN `date_time_start` date,IN `date_time_end` date)
BEGIN
DECLARE row_token VARCHAR(200);#定义类型
DECLARE row_appid VARCHAR(200);#定义类型
DECLARE row_create_time VARCHAR(200);#定义类型
-- 定义游标
DECLARE done INT;
-- 整理获取待更新数据
DECLARE rs_cursor CURSOR FOR
SELECT token,app_id as appid,date_time_start as create_time FROM fb_sdk_log.hear_beat_log FORCE INDEX (index_hear_log_createTime) WHERE create_time >= date_time_start AND create_time < date_time_end AND app_id IN ( 'fbglbdmtsd17050601', 'fbglxlmtsd18011001' ) GROUP BY token ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN rs_cursor;
cursor_loop:LOOP
FETCH
rs_cursor INTO row_token,row_appid,row_create_time; -- 取数据
IF done=1 THEN
leave cursor_loop;
END IF;
-- 更新表
INSERT INTO mtk_stat.middle_log (token ,appid,create_time) VALUES(row_token,row_appid,row_create_time);
END LOOP cursor_loop;
CLOSE rs_cursor;
END
#调用存储过程,插入中间表
call temp_heart('2020-09-01','2020-10-01')
步骤二: 将心跳表9月份整月数据拆成 30天,拿取每日数据匹配处理中间表middle_log
1.每日处理的存储过程
CREATE DEFINER=`mtk`@`%` PROCEDURE `temp_heart_deal`(IN `date_time_start` date,IN `date_time_end` date)
BEGIN
DECLARE row_token VARCHAR(200);#定义类型
-- DECLARE date_time_start DATETIME default '2020-09-01';#定义类型
-- DECLARE date_time_end DATETIME default '2020-09-02';#定义类型
DECLARE row_create_time VARCHAR(200);#定义类型
-- 定义游标
DECLARE done INT;
-- 整理获取待更新数据
DECLARE rs_cursor CURSOR FOR
SELECT token FROM sdk_log.hear_beat_log PARTITION (p20201001) WHERE create_time >= date_time_start AND create_time < date_time_end AND app_id IN ( 'fbglbdmtsd17050601', 'fbglxlmtsd18011001') GROUP BY token ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN rs_cursor;
cursor_loop:LOOP
FETCH rs_cursor INTO row_token; -- 取数据
IF done=1 THEN
leave cursor_loop;
END IF;
-- 更新表
UPDATE middle_log SET count =(count+1) where token =row_token AND create_time = date_time_start AND appid IN ( 'fbglbdmtsd17050601', 'fbglxlmtsd18011001');
END LOOP cursor_loop;
CLOSE rs_cursor;
END
2.程序循环调用temp_heart_deal
日期工具类方法:
private static final SimpleDateFormat DAY = getFormat("yyyy-MM-dd");
/**
* 计算两个日期之间相差的天数
* @param smdate 较小的时间
* @param bdate 较大的时间
* @return 相差天数
* @throws ParseException
*/
public static int daysBetween(Date smdate, Date bdate) {
Date formatSmdate = getDayDate(smdate);
Date formatBdate = getDayDate(bdate);
Calendar cal = Calendar.getInstance();
cal.setTime(formatSmdate);
long time1 = cal.getTimeInMillis();
cal.setTime(formatBdate);
long time2 = cal.getTimeInMillis();
long betweenDays = (time2 - time1) / (1000 * 3600 * 24);
return Integer.parseInt(String.valueOf(betweenDays));
}
/**
* method : 24、把date的天数增加offset
* @param date
* @param offset
* @return xx
*/
public static Date daysAddOrSub(Date date, int offset) {
return addOrSub(date, Calendar.DAY_OF_MONTH, offset);
}
private static Date addOrSub(Date date, int type, int offset) {
if (date == null)
return null;
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.get(type);
cal.set(type, cal.get(type) + offset);
return cal.getTime();
}
/**
* method : 13、根据Date获取"yyyy-MM-dd"字符串
* @param date
* @return xx
*/
public static String getDayStr(Date date) {
synchronized (DAY) {
return getStr(date, DAY);
}
}
private static String getStr(Date date, SimpleDateFormat format) {
if (date == null) {
return "";
}
return format.format(date);
}
public static List<String> getDayBteweenStartAndEnd(String dateStart,String dateEnd) throws ParseException {
synchronized (DAY){
Date dateStartDate = DAY.parse(dateStart);
Date dateEndDate = DAY.parse(dateEnd);
int dayNum = daysBetween(dateStartDate, dateEndDate);
List stings=new ArrayList(dayNum);
for (int i=0;i<dayNum;i++){
Date date = daysAddOrSub(dateStartDate, i);
stings.add(getDayStr(date));
}
return stings;
}
}
单元调用:运行执行
@Test
public void TempHeartDeal() throws ParseException {
List<String> dayBteweenStartAndEnd = DateUtil.getDayBteweenStartAndEnd("2020-09-01", "2020-10-01");
for (int i = 0; i < dayBteweenStartAndEnd.size() - 1; i++) {
String start = dayBteweenStartAndEnd.get(i);
String end = dayBteweenStartAndEnd.get(i + 1);
System.out.println(start + ":" + end);
//todo
//调用存储过程处理 call temp_heart_deal(start,end);
}
}