Mysql 根据月份分组并返回分组中的所有数据

现有数据如下:

交易描述 金额 时间

交易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 5000

2021年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 可以封装为一个实体,用于添加更多列表特性数据(汇总等)。

大概思路:

  1. 先获取查询列表中第一个数据初始化响应列表和初始化分类;
  2. 进入查询列表循环,先获取分类,然后与初始化分类比对;
  3. 若不同,更新初始化时间分类,响应列表重新初始化为当前分类数据及初始化响应列表;
  4. 相同则持续添加当前分类数据到响应列表;
  5. 跳出循环,返回响应列表;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值