MySQL:如何从里程周期中获取维护计划

问题描述

我有一个 MysqL 表,描述了铁路车辆的维护周期(大修类型和周期,以公里为单位):

CREATE TABLE `cycle_test` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,`type` varchar(2) COLLATE utf8_spanish_ci NOT NULL,`km` int(11) unsigned NOT NULL,PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci

我已按如下方式填充此表:

INSERT INTO `cycle_test` (`id`,`type`,`km`) VALUES (NULL,'R1','12000'),(NULL,'R2','24000'),'R3','72000'),'R4','144000');
SELECT type,km FROM cycle_test;
+------+--------+
| type | km     |
+------+--------+
| R1   |  12000 |
| R2   |  24000 |
| R3   |  72000 |
| R4   | 144000 |
+------+--------+

目标是获得保养计划表,包括整个周期内要进行的所有大修,以及每次大修的里程数,同时考虑到,当不同类型的大修重合时,等级最高的那个( R4 > R3 > R2 > R1) 取代排名最低的,如下图:

+--------+------+
| km     | type |
+--------+------+
| 12000  | R1   |
| 24000  | R2   |
| 36000  | R1   |
| 48000  | R2   |
| 60000  | R1   |
| 72000  | R3   |
| 84000  | R1   |
| 96000  | R2   |
| 108000 | R1   |
| 120000 | R2   |
| 132000 | R1   |
| 144000 | R4   |
+--------+------+

这个问题我已经在 PHP解决,但我正在寻找一个纯粹的 MysqL 解决方案,无论是会话变量还是存储过程。 (可能的)解决方案必须可针对不同的维护周期进行扩展(非硬编码)。 预先感谢您的帮助和/或提示

解决方法

好吧,在 MySQL 文档的帮助下,结果比我想象的要容易。首先,我创建了调度表(在生产中,它将是一个临时表):

CREATE TABLE `schedule_test` (
 `type` varchar(2) COLLATE utf8_spanish_ci NOT NULL,`km` int(11) unsigned NOT NULL,UNIQUE KEY `km` (`km`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci

UNIQUE KEY km 允许检测相同里程的不同等级大修的并发性。

然后我在数据库中创建了以下存储过程:

BEGIN
/* Declaration of variables,cursors and handlers */
DECLARE done INT DEFAULT 0;
DECLARE vTip CHAR(16);
DECLARE vKm,acKm INT;
DECLARE vFinal INT DEFAULT 0;
DECLARE cur1 CURSOR FOR SELECT type,km FROM cycle_test;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
/* end declaration */
TRUNCATE schedule_test; -- Get rid of any data
SELECT MAX(km) FROM cycle_test INTO vFinal; -- Find the final mileage of the cycle
OPEN cur1;
REPEAT
    FETCH cur1 INTO vTip,vKm; -- Read record from overhaul cycle
    IF NOT done THEN
        SET acKm = 0; -- Initialize mileage
        REPEAT
            SET acKm = acKm + vKm; -- Accumulate mileage
            INSERT INTO schedule_test (type,km) VALUES (vTip,acKm)
            ON DUPLICATE KEY UPDATE type=VALUES(type); -- Insert schedule; update type if an overhaul already exists
        UNTIL acKm = vFinal END REPEAT; -- until reach the end of cycle
    END IF;
UNTIL done END REPEAT;
CLOSE cur1;
END

这是运行程序后我想要的结果:

mysql> select * from schedule_test;
+------+--------+
| type | km     |
+------+--------+
| R1   |  12000 |
| R2   |  24000 |
| R1   |  36000 |
| R2   |  48000 |
| R1   |  60000 |
| R3   |  72000 |
| R1   |  84000 |
| R2   |  96000 |
| R1   | 108000 |
| R2   | 120000 |
| R1   | 132000 |
| R4   | 144000 |
+------+--------+
12 rows in set (0.00 sec)