最近用MySQL做统计的需求比较多,这里整理一些常用的场景方便后期查阅,同时也是抛砖引玉的过程。其中包括普通的分组统计,连续的每日统计,区间范围统计。
场景一:根据订单状态统计订单数量。
一个很常见,也很简单的统计需求。其中状态字段是订单实体的一个属性。
@Query("SELECT status, COUNT(id) FROM Order GROUP BY status") fun summaryOrderByStatus(): Array<Array<String>>?
场景二:根据订单中商品类目统计订单数量和金额。
比场景一稍微麻烦了一点,商品字段是订单实体的一个属性,而类目字段才是商品实体的一个属性。参考代码:(Kotlin语法)
@Query("SELECT commodity.category, COUNT(id), SUM(finalPrice) FROM Order GROUP BY commodity.category") fun summaryOrderByCommodityCategory(): Array<Array<String>>?
小结:
在做每日,每周,每月统计时,遇到返回日期不是连续的情况。
原因是数据库中没有值,而我们理想状态应该是:如果没有值则默认为零,使其数据是连续的日期。
场景三:统计结果日期可能不连续
如果数据库中某个时间段没有值,那统计出来的结果会缺这段时间。参考代码:(sql语句)
-- 统计每日 SELECT DATE_FORMAT(create_date,'%Y-%m-%d') as days, COUNT(id) count FROM order GROUP BY days; -- 统计每周 SELECT DATE_FORMAT(create_date,'%Y-%u') as weeks, COUNT(id) count FROM order GROUP BY weeks; -- 统计每月 SELECT DATE_FORMAT(create_date,'%Y-%m') as months, COUNT(id) count FROM order GROUP BY months;
场景四:统计结果日期连续
要让日期连续,又要代码优雅。说实话,困扰了我很久,一直没有找到很好的解决方法,虽然目前这个方法很挫。但可以解决问题。毕竟抓到老鼠的都是好猫。如果各位有好的建议,望赐教!
解决思路:
第二步参考代码(Kotlin语法)
val startDate = Calendar.getInstance() startDate.set(2018, 6, 1) val startTIme = startDate.timeInMillis val endDate = Calendar.getInstance() endDate.set(2028, 11, 30) val endTime = endDate.timeInMillis val oneDay = 1000 * 60 * 60 * 24L var time = startTIme val dates: MutableList<DateSummary> = arrayListOf() while (time<=endTime) { val dateSummary = DateSummary() dateSummary.date = SimpleDateFormat("yyyy-MM-dd").format(Date(time)) dateSummary.count = 0 dates.add(dateSummary) time += oneDay } dateSummaryRepository.saveAll(dates)
第三步统计每日的SQL语句
SELECT summary.oneDay, summary.count FROM ( SELECT DATE_FORMAT( created_date, '%Y-%m-%d' ) oneDay, COUNT(id) count FROM service_order WHERE created_date BETWEEN "2018-06-01" and "2018-08-01" GROUP BY oneDay UNION ALL ( SELECT DATE_FORMAT( date, '%Y-%m-%d' ) templateDay, count FROM date_summary WHERE date BETWEEN "2018-06-01" and "2018-08-01" GROUP BY templateDay ) ) summary GROUP BY summary.oneDay ORDER BY summary.oneDay ASC
小结:
这是一个较为常见的需求,比如按照年龄段统计人员分布情况,甚至要求分别统计男女人数分布情况。
场景五:根据小区年龄段统计人数
只根据年龄范围统计,没有其他限制条件,使用SUM只需要加一。
SELECT INTERVAL(age,10,20,30,40,50,60,70,80,90) AS ageRatio, SUM(1) AS count FROM user GROUP BY ageRatio
场景六:根据小区年龄段统计男女人数
在场景五的基础上多了一个区分性别,用流程控制函数来设置SUM加一的情况。
SELECT INTERVAL(age,10,20,30,40,50,60,70,80,90) AS ageRatio, SUM(CASE WHEN sex=1 THEN 1 ELSE 0 END) AS male, SUM(CASE WHEN sex=0 THEN 1 ELSE 0 END) AS female FROM user GROUP BY ageRatio
小结:
知道现在都是快餐文化,大家都很忙,很少有时间去揣摩各语法的特点。所以先把常用的场景写在前面,语法知识写在后面。
case when 条件1 then 值1 when 条件2 then 值2 ... else 值n end