祝大家1024节日快乐!
趁着公司断网这点时间,写了一篇博客和大家分享一下。。。。。
最近遇到一个问题就是做了一个报表的统计,下面拆分一下需求,简单的来说一说,就是统计一段时间内的数据量,可以当成是统计10月份每一天的访问量,要求如果当天的访问量是0的话,也要统计出来,不能跳过去。时间是连续的。
其实统计这个好做,就是group by +count就可以了,重要的是在当天的数据没有的话,分组里面就没有,然后0当然也出不来。所以就去网上搜了一些资料,这里总结一下前辈们的思路,详细的解释可以戳下面的连接,我就不在多啰嗦一遍了。
- 有一个单独的表存日历,到时候我们按照时间区间去连接这个表,因为日历表里面的时间是连续的。得到结果也就自然连续了。(从数据库角度出发,需要单独去维护一个数据表)
- 去连接一个足够大的带有日期的数据表,其实这就是相当于把这个表当成了一个日历表,但是这个表也有可能在某一天没有数据,那这样日期也就不连续了
- 从程序的角度出发,用代码去吧0补上,挨个检查有没有这天的数量,没有的话就填个0。需要写个循环。
https://blog.csdn.net/ajian759447583/article/details/61421399
https://blog.csdn.net/jie11447416/article/details/50887888
我的解决思路呢是受到第一篇大佬博客末尾的启发,用的union all ,用Java生成的时间片段。
就是这个方法,中间的时间片段我用java生成,给mybatis传一个list,然后foreach循环生成union。
java时间分片的方法
/**
* 日期范围 - 切片
*
*
* @param startDate 起始日期
* @param endDate 结束日期
* @param type 切片类型 1年 2月 3日 4小时
* @return 切片日期
*/
public static List<String> sliceUpDateRange(String startDate, String endDate ,int type ) {
List<String> rs = new ArrayList<>();
try {
int dt = Calendar.DATE;
String pattern = "yyyy-MM-dd";
if (type==1) {
pattern = "yyyy";
dt = Calendar.YEAR;
} else if (type==2) {
pattern = "yyyy-MM";
dt = Calendar.MONTH;
} else if (type==3) {
pattern = "yyyy-MM-dd";
dt = Calendar.DATE;
}else if (type==4) {
pattern = "yyyy-MM-dd HH";
dt = Calendar.HOUR_OF_DAY;
}
SimpleDateFormat sd = new SimpleDateFormat(pattern);
Calendar sc = Calendar.getInstance();
Calendar ec = Calendar.getInstance();
sc.setTime(sd.parse(startDate));
ec.setTime(sd.parse(endDate));
while (sc.compareTo(ec) < 1) {
rs.add(sd.format(sc.getTime()));
sc.add(dt, 1);
}
} catch (ParseException e) {
e.printStackTrace();
}
return rs;
}