IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 获取每天最高分数且最新的数据(java实现) -> 正文阅读

[大数据]获取每天最高分数且最新的数据(java实现)

背景

这篇讲一下我最近遇到的一个问题,并记录保存,方便下次直接查看。

刚开始会讲一些sql操作,后面会讲java代码实现,本文会从三种方法来实现该需求,如果你也正在遇到同样的问题,可以根据自身需求来选择哪种方式实现。

需求

提供一张表,字段有id、score、create_time(年月日)。

查询出每天的最高分最新的数据列表。

提供数据表结构

CREATE TABLE `t_score` (
  `id` int NOT NULL AUTO_INCREMENT,
  `score` int DEFAULT NULL COMMENT '分数',
  `create_time` varchar(20) COLLATE utf8mb4_bin DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

提供数据

INSERT INTO `t_score` VALUES (1, 5, '2021-09-15');
INSERT INTO `t_score` VALUES (2, 10, '2021-09-15');
INSERT INTO `t_score` VALUES (3, 10, '2021-09-15');
INSERT INTO `t_score` VALUES (4, 15, '2021-09-15');
INSERT INTO `t_score` VALUES (5, 15, '2021-09-15');
INSERT INTO `t_score` VALUES (6, 20, '2021-09-16');
INSERT INTO `t_score` VALUES (7, 15, '2021-09-16');
INSERT INTO `t_score` VALUES (8, 10, '2021-09-16');
INSERT INTO `t_score` VALUES (9, 30, '2021-09-16');
INSERT INTO `t_score` VALUES (10, 30, '2021-09-16');

实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-atHv2jCz-1631888585408)(access/2021-09-17/img_proxy.gif)]

拿起键盘就是干呀

闭着眼睛写sql

SELECT
	id,
	create_time,
	max( score ) 
FROM
	t_score 
GROUP BY
	create_time

注意:如果此处你的mysql报错:1055,group by不兼容时,点击此处解决

mysql查询group by 1055 问题完美解决,最简单最便捷的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YRk7a34k-1631888585411)(access/2021-09-17/统计分数最高.jpg)]

用时两分钟,搞定

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F4Kz4kgU-1631888585413)(access/2021-09-17/dog.gif)]

等等,再看下数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qsyOLOEW-1631888585414)(access/2021-09-17/原始数据.jpg)]

按照需求所说,查询出每天的最高分最新的数据列表

查询结果的id应该为5和10才对。

于是,于是,于是我就陷入了沉思…

终于,用了两个小时,写出了下面sql。

SELECT
	max( a1.id ) AS id,
	a1.score,
	a1.create_time 
FROM
	t_score a1
	JOIN ( SELECT create_time, max( score ) AS score FROM t_score GROUP BY create_time ) a2 ON a1.create_time = a2.create_time 
WHERE
	a1.score = a2.score 
GROUP BY
	a1.create_time 
ORDER BY
	a1.id

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MzJfeI2V-1631888585417)(access/2021-09-17/长sql.jpg)]

结果正确,没问题。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wPJ5LfdA-1631888585418)(access/2021-09-17/秒啊.gif)]

实现一

接下来开始写java代码咯,本文使用mybatis-plus来操作哦。

控制层

@RestController
@RequestMapping("score")
public class ScoreController {
    @Autowired
    private ScoreService service;

    @RequestMapping("list1")
    public List<ScoreDo> list1() {
        return service.list1();
    }
}

服务层

public interface ScoreService {
    /**
     * 查询列表
     * @return  列表
     */
    List<ScoreDo> list1();
}

服务实现层

@Service
public class ScoreServiceImpl extends ServiceImpl<ScoreMapper, ScoreDo> implements ScoreService {
    @Resource
    private ScoreMapper scoreMapper;

    @Override
    public List<ScoreDo> list1() {
        return scoreMapper.list1();
    }
}

数据交互层

public interface ScoreMapper extends BaseMapper<ScoreDo> {
    /**
     * 查询列表
     * @return
     */
    @Select("SELECT " +
            " max( a1.id ) as id, " +
            " a1.score as score, " +
            " a1.create_time as createTime " +
            "FROM " +
            " t_score a1 " +
            " JOIN ( SELECT create_time, max( score ) AS score FROM t_score GROUP BY create_time ) a2 ON a1.score = a2.score  " +
            "WHERE " +
            " a1.create_time = a2.create_time  " +
            "GROUP BY " +
            " a1.create_time  " +
            "ORDER BY " +
            " a1.id ASC")
    List<ScoreDo> list1();
}

实体类

@TableName("t_score")
public class ScoreDo {
    private Integer id;
    private Integer score;
    private String createTime;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getScore() {
        return score;
    }

    public void setScore(Integer score) {
        this.score = score;
    }

    public String getCreateTime() {
        return createTime;
    }

    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }

    @Override
    public String toString() {
        return "ScoreDo{" +
                "id=" + id +
                ", score=" + score +
                ", createTime='" + createTime + '\'' +
                '}';
    }
}

nice,posman测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KW9TyeMu-1631888585420)(access/2021-09-17/sql查询接口.jpg)]

没问题,返回结果也正确,这是第一种实现方式。

实现二

思考:既然我项目中使用了mybatis-plus,但是刚才的操作好像和plus没关系啊。

而且这个sql也过长,不容易阅读和理解。

能否把这个长SQL,改良为两个短sql。

说干就干,那我就先查询出最高分和日期,再查询最高的id。

控制层

@RequestMapping("list2")
public List<ScoreDo> list2() {
    return service.list2();
}

服务层

List<ScoreDo> list2();

服务实现层

@Override
public List<ScoreDo> list2() {
    QueryWrapper<ScoreDo> queryWrapper = new QueryWrapper<>();
    queryWrapper.select("create_time,max(score) as score");
    queryWrapper.groupBy("create_time");
    List<ScoreDo> list = this.list(queryWrapper);
    list.forEach(scoreDo -> {
        QueryWrapper<ScoreDo> scoreDoQueryWrapper = new QueryWrapper<>();
        scoreDoQueryWrapper.select("max(id) as id,score,create_time");
        scoreDoQueryWrapper.eq("create_time", scoreDo.getCreateTime());
        scoreDoQueryWrapper.eq("score", scoreDo.getScore());
        scoreDoQueryWrapper.groupBy("create_time");
        ScoreDo score = this.getOne(scoreDoQueryWrapper);
        scoreDo.setId(score.getId());
    });
    return list;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OLdVvdtt-1631888585421)(access/2021-09-17/接口查询2.jpg)]

结果没问题,这样拆分也比较好理解,但是又增加了数据库的交互,查询的数据如果有多个日期,则要查多少次数据库。还有没有更好的实现方法呢?思考。

实现三

可以使用java8新特性来处理。

控制层

@RequestMapping("list3")
public List<ScoreDo> list3() {
    return service.list3();
}

服务层

List<ScoreDo> list3();

服务实现层

@Override
public List<ScoreDo> list3() {
    List<ScoreDo> scoreDoList = scoreMapper.selectList(null);
    LinkedHashMap<String, ScoreDo> linkedHashMap = scoreDoList.stream().collect(
            Collectors.toMap(ScoreDo::getCreateTime,
                    Function.identity(), (c1, c2) -> c1.getScore() > c2.getScore() ? c1 : c2, LinkedHashMap::new));
    List<ScoreDo> list = new ArrayList<>(linkedHashMap.size());
    linkedHashMap.forEach((x, y) -> list.add(y));
    return list;
}

从代码来看3行解决,不得不说,java8真香。

  1. 首先是把数据都查询出来;

  2. 以时间来分组,这个LinkedHashMap的key就是时间;

  3. 按照分组后的时间进行比较数据,如果c1大于c2,则留下c1.依次比较;

  4. 转list返回。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XRkBzzZs-1631888585422)(access/2021-09-17/接口查询3.jpg)]

是不是第三种方法更简洁方便呢?

你还有其他的实现方法吗,欢迎沟通讨论,如果讲述不对的地方,欢迎指出来。

在这里插入图片描述

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-18 10:14:40  更:2021-09-18 10:17:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:59:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码