根据MySQL中以前的记录更新时间

时间:2016-07-14 17:17:49

标签: mysql

我有以下记录集:

+------------------------------------------+
| ID  | DateTimeValue       | UsedMinutes  |
| 1   | 2016-01-01 00:00:00 | 30           |
| 2   | 2016-01-01 00:00:00 | 45           |
| 3   | 2016-01-01 00:00:00 | 20           |
| 4   | 2016-02-02 00:00:00 | 30           |
| 5   | 2016-02-02 00:00:00 | 60           |
+------------------------------------------+

我想将它们转换为:

+------------------------------------------+
| ID  | DateTimeValue       | UsedMinutes  |
| 1   | 2016-01-01 00:00:00 | 30           |
| 2   | 2016-01-01 00:30:00 | 45           |
| 3   | 2016-01-01 01:15:00 | 20           |
| 4   | 2016-02-02 00:00:00 | 30           |
| 5   | 2016-02-02 00:30:00 | 60           |
+------------------------------------------+

因此,对于每个日期,时间值应根据先前的记录及其“使用的分钟数”字段递增。我的实际记录集有数千条记录,因此不能手动修改。

是否可以使用(单个)MySQL查询执行此操作?

2 个答案:

答案 0 :(得分:1)

我认为这将解决您的问题

mysql> select * from TRE;
+------+---------------+-------------+
| ID   | DateTimeValue | UsedMinutes |
+------+---------------+-------------+
|    1 | 2016-01-01    |          30 |
|    2 | 2016-01-01    |          45 |
|    3 | 2016-01-01    |          20 |
|    4 | 2016-02-02    |          30 |
|    5 | 2016-02-02    |          60 |
+------+---------------+-------------+
5 rows in set (0.00 sec)

mysql> select TRE.*,@curRank := @curRank + UsedMinutes as SUM_time from TRE,(SELECT @curRank := 0) r ORDER BY ID;
+------+---------------+-------------+----------+
| ID   | DateTimeValue | UsedMinutes | SUM_time |
+------+---------------+-------------+----------+
|    1 | 2016-01-01    |          30 |       30 |
|    2 | 2016-01-01    |          45 |       75 |
|    3 | 2016-01-01    |          20 |       95 |
|    4 | 2016-02-02    |          30 |      125 |
|    5 | 2016-02-02    |          60 |      185 |
+------+---------------+-------------+----------+
5 rows in set (0.03 sec)

mysql> select DATE_ADD(DateTimeValue, INTERVAL @curRank := @curRank + UsedMinutes MINUTE) from TRE,(SELECT @curRank := 0) r ORDER BY ID;
+-----------------------------------------------------------------------------+
| DATE_ADD(DateTimeValue, INTERVAL @curRank := @curRank + UsedMinutes MINUTE) |
+-----------------------------------------------------------------------------+
| 2016-01-01 00:30:00                                                         |
| 2016-01-01 01:15:00                                                         |
| 2016-01-01 01:35:00                                                         |
| 2016-02-02 02:05:00                                                         |
| 2016-02-02 03:05:00                                                         |
+-----------------------------------------------------------------------------+
5 rows in set (0.05 sec)

答案 1 :(得分:1)

你可以尝试一下:

SELECT 
t.ID,
t.expectedTime,
t.usedMin
FROM 
(
   SELECT
        ID,
        IF(@currentDateTime <> DateTimeValue, @runningTime :='0000-00-00 00:00:00' , 1) resetting,
        IF(@runningTime = '0000-00-00 00:00:00', DateTimeValue, @runningTime) AS expectedTime,
        @minuteToAddNext := UsedMinutes AS usedMin,
        @currentDateTime := DateTimeValue AS previousDateTime,
        @runningTime := IF(@runningTime = '0000-00-00 00:00:00', DateTimeValue + INTERVAL UsedMinutes MINUTE , @runningTime + INTERVAL UsedMinutes MINUTE) AS nextRowsValue
    FROM
            datetimetable
    CROSS JOIN (
            SELECT
                    @currentDateTime := '0000-00-00 00:00:00',
                    @minuteToAddNext := 0,
                    @runningTime := '0000-00-00 00:00:00'
    ) AS var
    ORDER BY DateTimeValue
) AS t;

WORKING DEMO 输出4列(一个额外的)

UPDATED WORKING DEMO 输出3列符合您的要求

<强>解释

扫描每一行时,将UsedMinutes值存储在名为@minuteToAddNext的变量中,如查询中所示:

@minuteToAddNext := UsedMinutes

在扫描下一行时,只有@minuteToAddNext值从同一DateTimeValue保存时,您的第一项任务才是将@minuteToAddNext值添加到dateTimeValue。这在查询中翻译如下:

DateTimeValue + INTERVAL IF(@currentDateTime = DateTimeValue, @minuteToAddNext , 0) MINUTE AS updatedDteTimeValue

看,如果上一行@currentDateTime = current row's DateTimeValue,那么您将从@minuteToAddNext获得IF。 (意思相同dateTimeValue)。

否则IF将返回0。所以,DateTimeValue + INTERVAL 0 MINUTE = DateTimeValue

修改

为了使用上述选择查询中生成的datetime值更新表,您需要运行以下查询:

UPDATE datetimetable DT 
INNER JOIN 
(
        SELECT
        ID,
        IF(@currentDateTime <> DateTimeValue, @runningTime :='0000-00-00 00:00:00' , 1) resetting,
        IF(@runningTime = '0000-00-00 00:00:00', DateTimeValue, @runningTime) AS expectedTime,
        @minuteToAddNext := UsedMinutes AS usedMin,
        @currentDateTime := DateTimeValue AS previousDateTime,
        @runningTime := IF(@runningTime = '0000-00-00 00:00:00', DateTimeValue + INTERVAL UsedMinutes MINUTE , @runningTime + INTERVAL UsedMinutes MINUTE) AS nextRowsValue
    FROM
            datetimetable
    CROSS JOIN (
            SELECT
                    @currentDateTime := '0000-00-00 00:00:00',
                    @minuteToAddNext := 0,
                    @runningTime := '0000-00-00 00:00:00'
    ) AS var
    ORDER BY DateTimeValue
) AS t
ON DT.ID = t.ID 
SET DT.DateTimeValue = t.expectedTime;