如何在MariaDB中高效合并同组用户的日期记录?
问题
我有一组用户记录,包含started(开始日期)、ends(结束日期)以及用户所属分组A、B、C,具体数据如下:
| started | ends | A | B | C |
|---|---|---|---|---|
| 2010/01/02 | 2010/02/02 | 1 | 0 | 1 |
| 2010/03/02 | 2010/04/02 | 1 | 0 | 1 |
| 2010/05/02 | 2010/06/02 | 1 | 0 | 1 |
| 2011/01/02 | 2011/02/02 | 0 | 0 | 1 |
| 2011/03/02 | 2011/04/02 | 0 | 0 | 1 |
使用MariaDB,需要将同一分组(A、B、C取值完全相同)的记录合并为一条,取该分组下最早的started日期和最晚的ends日期,预期合并结果如下:
| started | ends | A | B | C |
|---|---|---|---|---|
| 2010/01/02 | 2010/06/02 | 1 | 0 | 1 |
| 2011/01/02 | 2011/04/02 | 0 | 0 | 1 |
当前用存储过程+游标+临时表的方式实现,耗时较长,代码如下:
CREATE PROCEDURE loopOver() BEGIN DECLARE done BOOLEAN DEFAULT 0; DECLARE id BIGINT UNSIGNED; DECLARE cur CURSOR FOR SELECT user_id FROM table1 as f WHERE NOT EXISTS( -- temp table that contain already check records SELECT 1 FROM temp_table as t WHERE f.id = t.id); DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; FETCH cur INTO id; -- Get first row WHILE NOT done DO -- This where i create tmp table call creating_tmp_table(id); FETCH cur INTO id; -- Get next row END WHILE; CLOSE cur; END //
请问有没有更高效的实现方式?
更高效的实现方案
不需要用游标和临时表,直接用分组聚合查询就能完成需求,这是数据库原生优化的高效操作,完全避免游标逐行处理的性能损耗。
基础实现SQL
SELECT MIN(started) AS started, MAX(ends) AS ends, A, B, C FROM table1 GROUP BY A, B, C;
关键说明
- 核心逻辑:通过
GROUP BY A, B, C将所有分组完全相同的记录归为一组,再用MIN(started)取组内最早开始日期,MAX(ends)取组内最晚结束日期,直接得到预期的合并结果。 - 性能优势:分组聚合是数据库底层优化过的批量操作,数据量越大,对比游标逐行处理的速度差距越明显。
- 日期类型兼容:如果
started和ends是字符串格式,建议先转换为日期类型再聚合,确保日期比较的准确性:
SELECT MIN(STR_TO_DATE(started, '%Y/%m/%d')) AS started, MAX(STR_TO_DATE(ends, '%Y/%m/%d')) AS ends, A, B, C FROM table1 GROUP BY A, B, C;
内容的提问来源于stack exchange,提问作者Rody
相关产品推荐
相关产品推荐

