mysql一张表有属性id,a,b,time,id为uuid,当a和b多条记录相同时,取时间最早的那个
如果相同的记录(例如,a 和 b 的组合) 不是连续的,且希望对于每一组相同的 a 和 b 值,选择时间最早的记录,而不依赖它们是否在连续的行中,那么可以通过以下方式来实现:
解决方案
- 定义连续性: 连续的记录通常是基于
time排序的,因此可以通过ORDER BY time来保证记录的顺序。 - 使用变量:需要一个办法来 标识哪些记录是连续的。可以通过使用
@变量来对比当前记录与前一记录的a和b值是否相同。如果相同,则它们是连续的;如果不同,则认为它们是新的一组。 - 选取每组最早的记录:对于每组连续的
a和b值,选取time最早的一条记录。
SQL 查询
假设表名为 records,字段为 id (UUID), a, b, time。
SELECT
a,
b,
MIN(time) AS min_time
FROM (
SELECT
id,
a,
b,
time,
@group_id := IF(@prev_a = a AND @prev_b = b, @group_id, @group_id + 1) AS group_id,
@prev_a := a,
@prev_b := b
FROM records, (SELECT @prev_a := NULL, @prev_b := NULL, @group_id := 0) AS init
ORDER BY time
) AS grouped
GROUP BY a, b, group_id解释:
- 变量初始化:
@prev_a := NULL, @prev_b := NULL, @group_id := 0初始化了两个变量@prev_a和@prev_b用于存储前一条记录的a和b值,@group_id用于标识连续组。 - 连续性判断:
@group_id := IF(@prev_a = a AND @prev_b = b, @group_id, @group_id + 1)
如果当前记录的a和b与前一记录相同(即连续),则@group_id保持不变;否则,@group_id增加 1,表示新的一组开始。 - 时间最早记录选择:
在子查询中,使用MIN(time)来选择每组中时间最早的记录。
示例数据
假设 records 表如下所示:
| id | a | b | time |
|---|---|---|---|
| uuid1 | 1 | 2 | 2024-11-05 10:00:00 |
| uuid2 | 1 | 2 | 2024-11-05 09:00:00 |
| uuid3 | 1 | 2 | 2024-11-05 11:00:00 |
| uuid4 | 1 | 3 | 2024-11-05 08:00:00 |
| uuid5 | 1 | 3 | 2024-11-05 12:00:00 |
| uuid6 | 2 | 2 | 2024-11-05 08:30:00 |
假设要统计 a 和 b 连续的记录,最终只返回最早的时间记录(按时间排序)。
执行上述 SQL 查询后,返回的结果将会是:
| id | a | b | time |
|---|---|---|---|
| uuid2 | 1 | 2 | 2024-11-05 09:00:00 |
| uuid4 | 1 | 3 | 2024-11-05 08:00:00 |
| uuid6 | 2 | 2 | 2024-11-05 08:30:00 |
MyBatis-Plus 实现
在 MyBatis-Plus 中,可以将上面的查询语句作为原生 SQL 查询来实现。以下是如何在 Mapper 接口中定义自定义查询。
Mapper 接口
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.model.Record;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface RecordMapper extends BaseMapper<Record> {
@Select("SELECT a, b, MIN(time) AS min_time " +
"FROM ( " +
" SELECT id, a, b, time, " +
" @group_id := IF(@prev_a = a AND @prev_b = b, @group_id, @group_id + 1) AS group_id, " +
" @prev_a := a, " +
" @prev_b := b " +
" FROM records, (SELECT @prev_a := NULL, @prev_b := NULL, @group_id := 0) AS init " +
" ORDER BY time " +
") AS grouped " +
"GROUP BY a, b, group_id ")
List<Record> getEarliestRecordsForConsecutiveGroups();
}调用 Mapper 方法
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class RecordService {
@Autowired
private RecordMapper recordMapper;
public List<Record> getEarliestRecordsForConsecutiveGroups() {
return recordMapper.getEarliestRecordsForConsecutiveGroups();
}
}总结:
- 使用
@group_id变量来标识连续记录组,确保只有在a和b连续的情况下才合并记录。 - 对于每组连续的记录,使用
MIN(time)获取最早的记录。 - 这种方法适用于在不连续的记录中,只选择那些连续的记录进行统计。
10 条评论
2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com
2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
这篇文章不错!
对权力结构的解构充满勇气与智慧。
建议标注关键步骤的注意事项。
1
1
1