MySQL只更新(update)查询出数据的第一条或最后一条

本文介绍如何使用SQL语句更新数据库中根据创建时间查询出的数据集的最后一条记录。通过添加ORDER BY和DESC来实现对记录的降序排列,并结合LIMIT 1确保仅更新最后一条记录。

最近在做项目功能时,要求只更新根据创建时间查询出的数据集的最后一条。使用一般update语句全都更新。最后查阅网上及自己总结如下:

注意:LIMIT  n, 是数字符合条件的前N条记录,不是分页。

更新第一条:

UPDATE user_pay_all SET result='2', cdes='订购成功' WHERE uid like 'test' ORDER BY createtime LIMIT 1

更新最后一条:(就是降序)

UPDATE user_pay_all SET result='2', cdes='订购成功' WHERE uid like 'test' ORDER BY createtime DESC LIMIT 1

当然,也可以先Select查询出最后一条再通过id更新字段,但不推荐。

<think> 我们参考上述引用,特别是引用[2]中提到了两种方法:MySQL 5版本的写法和MySQL 8版本的写法(使用窗口函数)。用户明确要求使用窗口函数查询多条数据并取第一条数据,因此我们将重点放在引用[2]中的MySQL 8版本写法。 核心思路: 1. 使用窗口函数(如ROW_NUMBER())对数据进行分组(PARTITION BY)和排序(ORDER BY)。 2. 为每一行数据在其分组内分配一个序号(比如按时间倒序,那么最新的就是1)。 3. 外层查询选择序号为1的行,即每个分组的第一条。 具体步骤: 假设我们有一个表`user_info`,包含字段:user_id, class_id, user_name, time。我们想要每个class_id分组内最新(time最大)的第一条数据。 步骤1:使用ROW_NUMBER()窗口函数 在子查询中,我们按class_id分组(PARTITION BY class_id),并按time降序排序(ORDER BY time DESC),这样每个分组内时间最大的排在最前面,然后使用ROW_NUMBER()给每一行分配一个序号(rn)。 步骤2:外层查询过滤 然后在外部查询中,我们筛选rn=1的行,这样就得到了每个class_id分组的第一条(即最新的一条)。 具体SQL语句如下: ```sql SELECT user_id, class_id, user_name, time FROM ( SELECT user_id, class_id, user_name, time, ROW_NUMBER() OVER (PARTITION BY class_id ORDER BY time DESC) AS rn FROM user_info ) AS user WHERE rn = 1; ``` 注意:除了ROW_NUMBER(),我们也可以使用其他窗口函数,但注意: - ROW_NUMBER():会为每一行分配唯一的序号(即使排序字段相同,也会分配不同的序号,按照顺序1,2,3...)。 - RANK():如果排序字段相同,会分配相同的序号,并且会跳过下一个序号(例如1,1,3)。 - DENSE_RANK():如果排序字段相同,会分配相同的序号,但不会跳过序号(例如1,1,2)。 根据需求,如果要求取分组内的第一条(且排序字段可能重复时,如果重复我们只取一条),通常使用ROW_NUMBER()。 另外,引用[4]中也展示了类似的方法,使用MAX(last_update_time) OVER (PARTITION BY sku_code)来获取每个分组的最大时间,然后通过排序来展示数据。但用户要求取第一条数据,所以直接使用ROW_NUMBER()更直接。 因此,我们推荐使用ROW_NUMBER()窗口函数的方法。 相关问题: 1. 如果在一个分组内有两条数据的排序字段相同,且都想取来,应该使用什么窗口函数? 2. 除了ROW_NUMBER(),还有哪些窗口函数可以用来实现取分组内前几条数据? 3. 使用窗口函数和GROUP BY在性能上有什么差异? </think> ### MySQL窗口函数查询多条数据并取第一条数据的方法 使用窗口函数在MySQL查询多条数据并取每组第一条数据,核心是通过`PARTITION BY`分组和`ORDER BY`排序控制数据顺序,再用`ROW_NUMBER()`标记行号后筛选。以下是具体方法: #### 1. 基础语法(推荐) ```sql SELECT 字段列表 FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY 分组字段 ORDER BY 排序字段 DESC ) AS rn FROM 表名 ) AS tmp WHERE rn = 1; ``` - **`PARTITION BY 分组字段`**:按指定字段分组(如用户ID、商品类别等) - **`ORDER BY 排序字段 DESC`**:组内按指定字段降序排列(取最新数据) - **`rn = 1`**:筛选每组的第一条记录 #### 2. 应用示例 按班级分组获取每个班级最新注册的学生: ```sql SELECT user_id, class_id, user_name, reg_time FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY class_id ORDER BY reg_time DESC ) AS rn FROM students ) AS tmp WHERE rn = 1; ``` #### 3. 替代方案(兼容MySQL 5.7) 若使用不支持窗口函数的MySQL版本: ```sql SELECT s1.user_id, s1.class_id, s1.user_name, s1.reg_time FROM students s1 LEFT JOIN students s2 ON s1.class_id = s2.class_id AND s1.reg_time < s2.reg_time WHERE s2.user_id IS NULL; ``` #### 关键点说明 1. **窗口函数选择**: - `ROW_NUMBER()`:严格取第一条(即使排序字段相同) - `RANK()`/`DENSE_RANK()`:并列时返回多条记录 2. **排序控制**: - `ORDER BY reg_time DESC` → 取最新记录 - `ORDER BY reg_time ASC` → 取最早记录 3. **性能优化**: - 在`排序字段`上添加索引 - 避免在子查询中使用`SELECT *`,只查询必要字段 #### 完整案例 ```sql /* 获取每个商品分类下价格最高的商品 */ SELECT product_id, category, price FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY category ORDER BY price DESC ) AS rn FROM products ) AS ranked_products WHERE rn = 1; ``` > **注意**:MySQL 8.0+ 支持窗口函数,低于此版本需使用自连接查询实现[^2][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值