数据库分组
问题设置
A公司某月日交易报表,需要展示的数据有交易量,交易成功总次数以及总金额
解决的方法
收先想到的肯定是把交易数据按日分组,然后去做对应的运算,这样会出现一个问题,就是如果某天没数据的话,就会出现显示的数据不完整
- 数据库操作
在数据库建一个日历表,如图
然后和交易表做关联查询,就可得到连续的数据
这样虽然可以,但是为了一次查询新建一张表,并不可取 - 代码层面的实现
/**
* @param ledgerDailyDTOList 每日数据(有空的)
* @param beginTime 开始时间
* @param endTime 结束时间
* @return 补充无数据的天
*/
private List<LedgerDailyDTO> getStatistics(List<LedgerDailyDTO> ledgerDailyDTOList, LocalDateTime beginTime, LocalDateTime endTime) {
// 计算时间区间,相差天数
long days = endTime.toLocalDate().toEpochDay() - beginTime.toLocalDate().toEpochDay() + 1;
List<LedgerDailyDTO> statistics = new ArrayList<>();
for (int i = 0; i < days; i++) {
LocalDate day = endTime.toLocalDate().minusDays(days - 1 - i);
// 判断是否已存在
boolean flag = false;
for (LedgerDailyDTO dto : ledgerDailyDTOList) {
if (dto.getTransactionTime().equals(day)) {
flag = true;
statistics.add(dto);
break;
}
}
// 若不存在,则添加数据
if (!flag) {
statistics.add(i, new LedgerDailyDTO().setTransactionTime(day).setConsumPay(0).setConsumTime(0).setRefundPay(0).setRefundTime(0).setIncomeSum(0));
}
}
return statistics;
}
/**
* @param ledgerDailyDTOList 每日数据(有空的)
* @param beginTime 开始时间
* @param endTime 结束时间
* @return 补充无数据的天
*/
private List<LedgerDailyDTO> getStatisticsV2(List<LedgerDailyDTO> ledgerDailyDTOList, LocalDateTime beginTime, LocalDateTime endTime) {
// 计算时间区间,相差天数
long days = endTime.toLocalDate().toEpochDay() - beginTime.toLocalDate().toEpochDay() + 1;
List<LocalDate> localDateList = new ArrayList<>();
for (int i = 0; i < days; i++) {
localDateList.add(endTime.toLocalDate().minusDays(days - 1 - i));
}
List<LocalDate> list = ledgerDailyDTOList.stream().map(ledgerDailyDTO -> ledgerDailyDTO.getTransactionTime()).collect(Collectors.toList());
localDateList.removeAll(list);
localDateList.stream().forEach(localDate -> ledgerDailyDTOList.add(new LedgerDailyDTO().setTransactionTime(localDate).
setConsumPay(0).setConsumTime(0).setRefundPay(0).setRefundTime(0).setIncomeSum(0)));
return ledgerDailyDTOList.stream().sorted(Comparator.comparing(LedgerDailyDTO::getTransactionTime)).collect(Collectors.toList());
}
上面是两种不同的实现方式,其实算法是差不多的,都是把需要的数据线造出来,然后遍历,把空的数据补上或者置空
注意
以后分组的地方要尤其注意此类问题的取舍,是不是该维护空数据