统计用户在各个月份的活跃(较大量数据)

需求:统计用户在各个月份的活跃(演示一个月的数据),一个用户在同一天会多次活跃,只记做一次

基本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);
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_42011565/article/details/111832243
今日推荐