通过计算更新mysql行

时间:2015-04-21 23:08:16

标签: mysql

====================================================================
| name | serial_id | timestamp           | cumulative | difference |
====================================================================
|  X   |    AA01   | 2014-12-16 12:50:01 |    832     |            |
|  Y   |    AB02   | 2014-12-16 12:50:01 |   1526     |            |
|  X   |    AA01   | 2014-12-16 12:51:01 |    835     |      3     |

嗨大家好,MySQL新手再来一次,

前一段时间,我构建了一个这样的数据库,作为跟踪一堆系统的方法。这些系统具有计数器,该计数器是累积数。我想追溯更新MySQL表,并添加一个列,让我区分这些计数器,基本上,更新行并添加" 3"。这里有皱纹,表中没有唯一的ID键,但您可以考虑serial_id + timestamp a"复合键"。为了使用这样的计算更新整个大规模表,我需要什么SQL语句。

1 个答案:

答案 0 :(得分:0)

获得结果的SQL语句是:

select t.*,
       (t.cumulative -
        (select t2.cumulative
         from table t2
         where t2.name = t.name
         order by timestamp desc
         limit 1
        )
       ) as diff
from table t;

在MySQL中,您可以使用join

将其置于更新中
update table t join
       (select t.*,
               (t.cumulative -
                (select t2.cumulative
                 from table t2
                 where t2.name = t.name
                 order by timestamp desc
                 limit 1
                )
               ) as diff
        from table t
       ) tt
       on t.name = tt.name and t.timestamp = tt.timestamp
    set t.difference = tt.diff
    where tt.diff is not null;

使用变量的另一种方法有点麻烦但可能更快。这很棘手,因为您无法初始化查询中的变量,因此它们始终是字符串:

update table t
    set t.difference = (t.cumulative - 
                        (case when @n = name                                       -- name doesn't change so use previous value
                              then (case when (@p := @prev) = NULL then 0          -- guaranteed to fail
                                         when (@prev := cumulative) = NULL then 0  -- guaranteed to fail
                                         else @p
                                    end)
                              when (@n := name) = NULL then 0                      -- guaranteed to fail
                              else NULL
                         end
                        )
    order by t.name, t.timestamp

变量逻辑相当复杂 - 在MySQL中获取先前的值有点困难,因为所有逻辑都必须适合单个语句。 case用于处理逻辑中的多个步骤。

此外,使用table(name, timestamp)上的索引可以更好地工作。