现有数据如下:
交易描述 金额 时间
交易A 1000 2021-01-28
交易B 2000 2021-01-30
交易C 3000 2021-02-03
交易D 4000 2021-02-04
交易E 5000 2021-02-04
交易F 6000 2021-03-05
要求:查出交易流水信息,按时间分类倒序展示,例如:
2021年3月
交易F 2021-03-05 6000
2021年2月
交易C 2021-02-03 3000
交易D 2021-02-04 4000
交易E 2021-02-04 50002021年1月
交易A 2021-01-28 1000
交易B 2021-01-30 2000
刚开始想按照年月时间进行分组,但是分组后只能得到该分组的第一条数据。
SELECT
translation,
translationDate,
amount,
DATE_FORMAT(translationDate,'%Y-%m') AS yearMonth
FROM datatable
GROUP BY yearMonth
ORDER BY translationDate desc;
交易描述 金额 时间 yearMonth
交易F 6000 2021-03-05 2021-03
交易E 5000 2021-02-04 2021-02
交易B 2000 2021-01-30 2021-01
由于本人sql水平有限,不知道如何向下扩展查询分组内所有的数据,于是最后决定按交易时间倒序查询所有数据后后端进行封装。
大致思路:
- 使用Map封装数据,key 为对应的月份,value为月份下的交易流水列表;
- 考虑到要按顺序保存月份,所以选择 LinkedHashMap;
- 遍历按时间倒序查询的所有交易流水,判断年月的key是否相同,不同则更新key ,插入对应的数据;
SELECT
translation,
translationDate,
amount
FROM datatable
ORDER BY translationDate desc;
// 1. 倒序查询所有交易流水信息
List<TranslateInfo> list = translateInfoService.selectList(params);
// 2.1 封装数据,map的key为 年-月 value为 年月对应的数据列表
Map<String, List<TranslateInfo>> dataMap = new LinkedHashMap();
// 2.2 封装 value
List<TranslateInfo> dataList = new ArrayList();
// 获取第一个数据的时间日期
LocalDate date = list.get(0).getTransactionDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
// 第一个 key
String keyYearMonth = date.format(DateTimeFormatter.ofPattern("yyyy-MM"));
// 遍历所有数据,当时间日期不同于上面的时间日期时创建一个新的 List
for (TransactionInfo info : list) {
String key = info.getTransactionDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().format(DateTimeFormatter.ofPattern("yyyy-MM"));
if (!keyYearMonth.equals(key)) {
keyYearMonth = key;
dataList = new ArrayList();
}
dataList.add(info);
dataMap.put(keyYearMonth, dataList);
}
Map 可以封装为一个实体,用于添加更多列表特性数据(汇总等)。
大概思路:
- 先获取查询列表中第一个数据初始化响应列表和初始化分类;
- 进入查询列表循环,先获取分类,然后与初始化分类比对;
- 若不同,更新初始化时间分类,响应列表重新初始化为当前分类数据及初始化响应列表;
- 相同则持续添加当前分类数据到响应列表;
- 跳出循环,返回响应列表;