MySQL查询需求:获取同表各记录字段的最新版本值
针对每组data_record_id和data_field_id获取最大revision对应的value
这个需求我经常遇到,在MySQL里有两种常用的实现方式,看你的MySQL版本来选就行:
方法一:兼容低版本MySQL的子查询关联法
如果你的MySQL版本是5.x及更早(不支持窗口函数),用这个方案最稳妥:
假设你的数据表名为data_records,核心字段是data_record_id、data_field_id、data_record_revision_id和value,可以这么写:
SELECT t1.data_record_id, t1.data_field_id, t1.value FROM data_records t1 INNER JOIN ( -- 第一步:先算出每个(记录ID,字段ID)组合的最大版本ID SELECT data_record_id, data_field_id, MAX(data_record_revision_id) AS max_rev_id FROM data_records GROUP BY data_record_id, data_field_id ) t2 ON t1.data_record_id = t2.data_record_id AND t1.data_field_id = t2.data_field_id AND t1.data_record_revision_id = t2.max_rev_id;
逻辑说明:
- 子查询
t2通过GROUP BY按data_record_id和data_field_id分组,用MAX()函数拿到每组的最大版本ID; - 把原表
t1和子查询t2关联,匹配三个字段(记录ID、字段ID、版本ID),就能精准定位到每组中版本最高的那条记录,进而拿到对应的value。
方法二:MySQL 8.0+ 窗口函数法
如果你的MySQL版本是8.0或更高,用窗口函数会更简洁,代码可读性也更好:
SELECT data_record_id, data_field_id, value FROM ( SELECT data_record_id, data_field_id, value, -- 按(记录ID,字段ID)分组,每组内按版本ID降序排序,给每条记录标记行号 ROW_NUMBER() OVER ( PARTITION BY data_record_id, data_field_id ORDER BY data_record_revision_id DESC ) AS row_num FROM data_records ) ranked_data -- 只保留每组的第一行(也就是版本ID最大的那条记录) WHERE row_num = 1;
逻辑说明:
- 内层查询用
ROW_NUMBER()窗口函数,给每个(data_record_id, data_field_id)分组里的记录按版本ID从大到小排序,行号为1的就是我们要的最高版本记录; - 外层查询筛选出
row_num = 1的结果,直接得到目标数据。
特殊情况处理:
如果同一个分组里存在多条版本ID相同且都是最大值的记录,用ROW_NUMBER()只会返回其中一条(随机)。要是想把这些记录都返回,可以把ROW_NUMBER()换成RANK(),这样相同最大版本ID的记录行号都会是1。
内容的提问来源于stack exchange,提问作者Gotrekk
相关产品推荐
相关产品推荐

