2025-07-09T02:15:46.png

B站视频里的营业额统计是通过日期循环查询对应的金额,这样会执行多查询,对数据库压力过大。

这里可以使用GROUP BY实现。

    <select id="getTurnoverStatistics" resultType="java.util.Map">
        SELECT 
            DATE(order_time) as orderDate,
            IFNULL(SUM(amount), 0) as turnover
        FROM orders 
        WHERE status = 5 
            AND DATE(order_time) BETWEEN #{beginDate} AND #{endDate}
        GROUP BY DATE(order_time)
        ORDER BY orderDate
    </select>

查询结果如下
2025-07-09T02:23:45.png

具体实现方法:

public TurnoverReportVO getTurnoverStatistics(LocalDate begin, LocalDate end) {
        log.info("查询营业额统计,开始日期:{},结束日期:{}", begin, end);
        
        // 1. 生成日期列表(使用Stream API优化)
        List<LocalDate> dateList = begin.datesUntil(end.plusDays(1))
                .collect(Collectors.toList());
        
        // 2. 查询数据库获取营业额数据
        List<Map<String, Object>> turnoverData = orderMapper.getTurnoverStatistics(begin, end);
        
        // 3. 将数据库结果转换为Map便于查找
        Map<LocalDate, BigDecimal> turnoverMap = turnoverData.stream()
                .collect(Collectors.toMap(
                    data -> ((java.sql.Date) data.get("orderDate")).toLocalDate(),
                    data -> (BigDecimal) data.get("turnover")
                ));
        
        // 4. 组装完整的日期和营业额列表(处理缺失日期)
        String dateListStr = dateList.stream()
                .map(date -> date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                .collect(Collectors.joining(","));
        
        String turnoverListStr = dateList.stream()
                .map(date -> turnoverMap.getOrDefault(date, BigDecimal.ZERO).toString())
                .collect(Collectors.joining(","));
        
        log.info("营业额统计完成,共{}天数据", dateList.size());
        
        // 5. 构建返回对象
        return TurnoverReportVO.builder()
                .dateList(dateListStr)
                .turnoverList(turnoverListStr)
                .build();
    }
最后修改:2025 年 07 月 09 日
如果觉得我的文章对你有用,请随意赞赏