Mysql分组取最新一条记录

news/2024/9/22 16:41:58 标签: mysql, 数据库

文章目录

  • Mysql分组取最新一条记录
    • 1. 数据准备
    • 1. 方法1:使用子查询获取每个组的最大时间戳,然后再次查询获取具体记录(如果时间戳是唯一的)
    • 2. 方法2:使用窗口函数(MySQL 8.0+)
    • 3. 方法3:使用LEFT JOIN(如果时间戳是唯一的)
    • 4. 方法4:如果ID是自增长的,并且与时间戳保持一致,则可以直接使用MAX(ID)
    • 5. 总结

Mysql分组取最新一条记录

1. 数据准备

CREATE TABLE records (  
    id INT AUTO_INCREMENT PRIMARY KEY,  
    category_id INT NOT NULL,  
    data VARCHAR(255) NOT NULL,  
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP  
);
-- 插入一些示例数据  
INSERT INTO records (category_id, data) VALUES  
(1, '这是分类1的第一条记录'),  
(2, '分类2的数据'),  
(1, '分类1的另一条记录'),  
(3, '第三条分类的数据'),  
(2, '分类2的更新数据'),  
(1, '分类1的最新记录'),  
(4, '新分类的数据');

1. 方法1:使用子查询获取每个组的最大时间戳,然后再次查询获取具体记录(如果时间戳是唯一的)

假设你有一个表records,其中包含字段id(主键,自增),category_iddatacreated_at(记录创建时间)。

SELECT r1.*
FROM records r1
INNER JOIN (
    SELECT category_id, MAX(created_at) AS latest_created_at
    FROM records
    GROUP BY category_id
) r2 ON r1.category_id = r2.category_id AND r1.created_at = r2.latest_created_at;

这个查询首先在子查询中为每个category_id找到最新的created_at时间,然后主查询将这个时间与原始表中的记录进行匹配,以获取每个分组的最新的完整记录。
弊端:统一分组不能出现created_at相同的情况,否则分组不唯一

2. 方法2:使用窗口函数(MySQL 8.0+)

如果你的MySQL版本是8.0或更高,你可以使用窗口函数来简化查询。

WITH RankedRecords AS (
    SELECT *,
           ROW_NUMBER() OVER(PARTITION BY category_id ORDER BY created_at DESC) AS rn
    FROM records
)
SELECT * FROM RankedRecords
WHERE rn = 1;

-- 或
SELECT
  * 
FROM
  ( SELECT *, ROW_NUMBER( ) OVER ( PARTITION BY category_id ORDER BY created_at DESC ) AS rn FROM records ) t 
WHERE
  t.rn =1

这里,ROW_NUMBER()窗口函数为每个category_id分组内的记录分配一个唯一的序号,基于created_at降序排列。因此,每个分组中created_at最新的记录将获得序号1。然后,通过在外层查询中选择序号为1的记录,你可以获取每个分组的最新记录。


弊端:虽然分组是唯一的,但是取的分组不是最新一条记录,任然要求时间戳是唯一

3. 方法3:使用LEFT JOIN(如果时间戳是唯一的)

如果每个category_idcreated_at的组合是唯一的,你可以使用LEFT JOIN来实现:

SELECT r1.*
FROM records r1
LEFT JOIN records r2 
    ON r1.category_id = r2.category_id AND r1.created_at < r2.created_at
WHERE r2.id IS NULL;

这个查询尝试为r1中的每条记录找到同一category_id下但created_at更晚的记录(r2)。如果找不到这样的记录(即r2.id IS NULL),则r1中的记录就是该分组中的最新记录。

4. 方法4:如果ID是自增长的,并且与时间戳保持一致,则可以直接使用MAX(ID)

一般时间和主键id是正向关系,比如id大的插入时间就会比较大,我们可以以id为准来查询

SELECT * from records where id in(select  max(id) from records group by category_id)

-- 或

SELECT
  r.* 
FROM
  records r
  INNER JOIN ( SELECT category_id, max( id ) maxid FROM records GROUP BY category_id ) t ON t.category_id = t.category_id 
  AND r.id = t.maxid


5. 总结

  1. 时间戳唯一的情况下1、2、3方法都能满足要求
  2. 时间戳不唯一的情况下,考虑4方法,需要确认id是不是正向的

http://www.niftyadmin.cn/n/5670597.html

相关文章

vue3扩展echart封装为组件库-快速复用

ECharts ECharts&#xff0c;全称Enterprise Charts&#xff0c;是一款由百度团队开发并开源&#xff0c;后捐赠给Apache基金会的纯JavaScript图表库。它提供了直观、生动、可交互、可个性化定制的数据可视化图表&#xff0c;广泛应用于数据分析、商业智能、网页开发等领域。以…

excel 单元格一直显示年月日

excel 单元格一直显示年月日&#xff0c;在单元格上右键选择单元格格式&#xff0c;选择日期时单元格会显示成日期格式

QT快速安装使用指南

在Ubuntu 16.04上安装Qt可以通过多种方式进行。以下是使用Qt在线安装程序和apt包管理器的两种常见方法&#xff1a; 方法一&#xff1a;使用Qt在线安装程序 下载Qt在线安装程序 访问Qt官方网站&#xff1a;Try Qt | Develop Applications and Embedded Systems | Qt找到并下载…

串口助手的qt实现思路

要求实现如下功能&#xff1a; 获取串口号&#xff1a; foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {qDebug() << "Port: " << serialPortInfo.portName(); // e.g. "COM1"qDebug() <<…

机器学习04-逻辑回归(python)-02原理与损失函数

​​​​​​​ 1. 逻辑回归概念 逻辑回归&#xff08;Logistic Regression&#xff09; 是一种 分类模型&#xff0c;主要用于解决 二分类问题&#xff08;即分成两类&#xff0c;如是否通过、是否患病等&#xff09;。逻辑回归的目标是根据输入的特征预测一个 概率&#xff0…

【电路笔记】-运算放大器积分器

运算放大器积分器 文章目录 运算放大器积分器1、概述2、运算放大器积分器的表示2.1 理想积分器2.2 交流响应2.3 输出公式3、限制4、总结1、概述 在我们之前与运算放大器相关的大多数文章中,配置都是基于带有电阻器作为反馈环路、分压器或互连许多运算放大器的一部分的放大器。…

【MySQ】在MySQL里with 的用法

在MySQL中&#xff0c;WITH语句通常与公用表表达式&#xff08;Common Table Expressions&#xff0c;简称CTE&#xff09;一起使用。CTE是一种临时的结果集&#xff0c;类似于视图或子查询&#xff0c;它们在查询中被定义并且可以在一个或多个SELECT、INSERT、UPDATE或DELETE语…

摆脱困境并在iPhone手机上取回删除照片的所有解决方案

您是否无意中从 iPhone 中删除了照片&#xff1f;您&#xff0c;无需惊慌&#xff0c;因为您可以使用以下方法恢复所有照片。 如果您长时间使用 iPhone&#xff0c;您应该知道 iOS 提供了许多 Android 不提供的备份功能。例如&#xff0c;您的所有照片都会自动备份到 iCloud 存…