目录
- 苍穹外卖day11
- 一:apache-Echarts简单了解
- 二:营业额统计
- 四:用户统计
- 五:订单统计
- 六:销量排名统计
- 总结
苍穹外卖day11
一:apache-Echarts简单了解
二:营业额统计
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
这个地方传入的是起始和终止时间,我们要再写一个接口来完成这个功能:
controller:
@GetMapping("/turnoverStatistics")
public Result turnover(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin, @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){TurnoverReportVO turnoverReportVO= reportService.turnover(begin,end);return Result.success(turnoverReportVO);
}
这里为了保证传入的时间格式和我们想要的一样,最后把时间格式使用DateTimeFormat转化一下,然后调用方法获取我们的vo对象,vo对象中有日期字符串,还有我们的营业额的数据
service:
@Override
public TurnoverReportVO turnover(LocalDate begin, LocalDate end) {List<LocalDate> dates=new ArrayList<>();while (!begin.equals(end)){dates.add(begin);begin=begin.plusDays(1);}dates.add(end);List<Long> counts=new ArrayList<>();for (LocalDate date : dates) {Long count= orderMapper.sumTurnover(date);if (count==null){count=0L;}counts.add(count);}String dateList = StringUtils.join(dates, ",");String turnoverList = StringUtils.join(counts, ",");TurnoverReportVO turnoverReportVO = TurnoverReportVO.builder().dateList(dateList).turnoverList(turnoverList).build();return turnoverReportVO;}
这里我们首先获取字符串集合,如何获取呢:我们知道首和尾,我们获取中间的只需要首每次加一天就行,直到等于尾,那么我们使用循环来获取,将日期的数据放入集合,然后我们再遍历日期集合,根据日期来获取当前的营业额,然后如果没有营业额返回的是null,最好将其转成0这样在折线图中显示的好看些,然后使用string’utils中的join方法将集合转成字符串;然后再封装好就行了;
mapper:
@Select("select sum(amount) from orders where DATE_FORMAT(order_time,'%Y-%m-%d')=#{date} and status=6 ")
Long sumTurnover(LocalDate date);
因为获取营业额,我们使用的是sum来对当天的营业额求和,然后我们数据库中的日期和我们传入的日期格式不同,我们要进行转换,然后就能进行比较了,然后营业额统计的是已完成的订单,所有对status也有限制;
四:用户统计
controller:
@GetMapping("/userStatistics")
public Result userOver(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin, @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){UserReportVO userReportVO= reportService.userOver(begin,end);return Result.success(userReportVO);
}
一样的把日期的格式转换一下;
service:
@Override
public UserReportVO userOver(LocalDate begin,LocalDate end) {List<LocalDate>dateList=new ArrayList<>();while (!begin.equals(end)){dateList.add(begin);begin=begin.plusDays(1);}dateList.add(end);List<Long> totalUserList= new ArrayList<>();List<Long> newUserList=new ArrayList<>();for (LocalDate localDate : dateList) {Long l= userMapper.select(localDate);Long newNumber= userMapper.selectByCreatTime(localDate);totalUserList.add(l);newUserList.add(newNumber);}String totalUserLists = StringUtils.join(totalUserList, ",");String newUserLists = StringUtils.join(newUserList, ",");String dateLists = StringUtils.join(dateList, ",");UserReportVO userReportVO = UserReportVO.builder().totalUserList(totalUserLists).newUserList(newUserLists).dateList(dateLists).build();return userReportVO;
}
这里也是先去将日期的所有值通过循环全部加入到集合中,然后再遍历日期,查找当前日期的新增用户数和用户总数;最后再使用工具类将集合转成字符串,然后再封装到vo对象中;
mapper:
@Select("select count(*) from sky_take_out.user where date_format(create_time,'%Y-%m-%d')<=#{localDate}")
Long select(LocalDate localDate);
@Select("select count(*) from sky_take_out.user where date_format(create_time,'%Y-%m-%d') =#{localDate}")
Long selectByCreatTime(LocalDate localDate);
用户总数就是当前日期前创建所有的用户数,新增用户是当前日期创建的用户
注意:这里count的结果可以为0,不会为空的,所以不用再判断是否为空转换了
五:订单统计
controller:
@GetMapping("/ordersStatistics")
public Result orderOver(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){OrderReportVO orderReportVO= reportService.orderOver(begin,end);return Result.success(orderReportVO);}
这里和之前一样就行。
service:
@Override
public OrderReportVO orderOver(LocalDate begin, LocalDate end) {List<LocalDate> localDates=new ArrayList<>();while (!begin.equals(end)){localDates.add(begin);begin=begin.plusDays(1);}localDates.add(end);List<Long> orderCountList=new ArrayList<>();List<Long> validOrderCountList=new ArrayList<>();for (LocalDate localDate : localDates) {Long orderCountDate= orderMapper.count(localDate,null);orderCountList.add(orderCountDate);Long validCountDate = orderMapper.count(localDate, Orders.COMPLETED);validOrderCountList.add(validCountDate);}Long orderCount=orderMapper.count(null,null);Long validOrderCount=orderMapper.count(null,Orders.COMPLETED);Double orderCompletionRate=0.0;if (orderCount != 0) {orderCompletionRate=(double)validOrderCount/orderCount;}OrderReportVO orderReportVO = OrderReportVO.builder().orderCompletionRate(orderCompletionRate).totalOrderCount(Math.toIntExact(orderCount)).dateList(StringUtils.join(localDates, ",")).orderCountList(StringUtils.join(orderCountList, ",")).validOrderCountList(StringUtils.join(validOrderCountList, ",")).validOrderCount(Math.toIntExact(validOrderCount)).build();return orderReportVO;
}
这里要查的数据比较多一共有6个,第一个是日期的字符串,我们先将其存在集合中,同样的先通过循环把日期值传给集合;第二个和第三个是有效订单和总订单的字符串,同样的因为是求一天的所以我们遍历日期集合,然后将日期数据传入到mapper中,因为是动态sql所以我们传入的参数有区别,有效订单要限制订单的状态,必须是已完成,这个我们要传入进去,而总订单没有限制我们只需要传入日期,状态设为null就行,第四个是订单总数:我们直接将其传入mapper,然后参数都为空就是全部的订单数,第五个是有效订单数,这个呢就是要限定状态,然后就是订单的有效率是有效订单数/订单总数,这里我们获得的订单总数和有效订单数都是long的整形数组,所以我们如果直接除结果可能是0,我们可以对其中一个进行类型转换,这样结果的类型也会转换,这里设计到除法就要判断一下除数是否为0,否则会报错;然后我们将其封装到vo对象,其中的集合我们使用stringutils将其转成字符串;
mapper:
我们使用动态sql上面4句sql调用的都是同一个方法,提高方法的利用率:
</select>
<select id="count" resultType="java.lang.Long">select count(id) from orders<where><if test="localDate!=null">date_format(order_time,'%Y-%m-%d') =#{localDate}</if><if test="status!=null">and status=#{status}</if></where>
</select>
一共就两个可变参数;
六:销量排名统计
这部分的sql是整个项目里最复杂的,涉及到聚合函数,分组查询,排序查询,分页查询。我们来看一下:
controller:
@GetMapping("/top10")
public Result salesTop10(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end){SalesTop10ReportVO reportVO= reportService.salesTop10(begin,end);return Result.success(reportVO);
}
同样是接收指定格式的日期字符串,然后调用service的方法;
service:
@Override
public SalesTop10ReportVO salesTop10(LocalDate begin, LocalDate end) {List<String> names = ordeiDetailMapper.reportName(begin, end);List<Long> numbers = ordeiDetailMapper.reportNumber(begin, end);String name = StringUtils.join(names, ",");String number = StringUtils.join(numbers, ",");SalesTop10ReportVO reportVO = SalesTop10ReportVO.builder().nameList(name).numberList(number).build();return reportVO;
}
这里service层我写的就比较简单了,通过两个sql一个获取菜品名称,一个获取菜品的销量;然后再将集合转成字符串,再封装成vo对象传给controller;
mapper:
@Select("select d.name from sky_take_out.order_detail d left join sky_take_out.orders o on o.id = d.order_id" +" where date_format(o.order_time,'%Y-%m-%d')>=#{begin} and date_format(o.order_time,'%Y-%m-%d')<=#{end} and o.status=5 group by d.name order by sum(d.number) desc limit 0,10")
List<String> reportName(LocalDate begin, LocalDate end);
@Select("select sum(d.number) from sky_take_out.order_detail d left join sky_take_out.orders o on o.id = d.order_id" +" where date_format(o.order_time,'%Y-%m-%d')>=#{begin} and date_format(o.order_time,'%Y-%m-%d')<=#{end} and o.status=5 group by d.name order by sum(d.number) desc limit 0,10")
List<Long> reportNumber(LocalDate begin, LocalDate end);
大体思路是这样的,我们首先要查询订单详情表,因为只有那里有菜品或者套餐的信息,然后因为我们要返回的是某个时间段的销量,而订单详情表没有日期相关信息,我们只能通过逻辑外键来联系订单表获取下单时间,同时订单的状态是已完成的才能计入销量,所以我们首先要多表查询,然后因为整个订单详情表中菜品的可以有多条数据,我们统计的是每个菜品的销量,所以我们按照菜品的名称进行分组,然后我们还要查询销量排名前十的所以首先要进行排序,排序的依据就是每组的number求和,前十我们就是要进行分页查询;这就是大体的思路。
总结
今天对前端的技术:echarts进行了简单了解,然后进行了营业额统计,用户统计,订单统计,还有top10的排名统计