祝大家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;
}