mysql检测字段值的变化

时间:2015-06-22 13:34:48

标签: mysql

我在这里发现了一个非常相似的问题,完全相同的标题:Mysql, Check field value change?,但这不是我需要的。

DB:MySql,表:tbl_geodata

我有疑问:

SELECT id,timestamp,ver_fw FROM tbl_geodata
WHERE imei LIKE '353227026533507'

结果是:

--Full data
+------+---------------------+--------+
| id   | timestamp           | ver_fw |
+------+---------------------+--------+
                 ...
                 ...
| 813  | 2014-09-10 11:24:01 | 2.5.0  |       
| 1457 | 2014-09-15 14:07:03 | 2.5.0  |
| 1458 | 2014-09-15 14:15:33 | 2.5.0  |
| 1467 | 2014-09-15 15:08:29 | 2.5.0  |
| 1468 | 2014-09-15 15:19:36 | 2.5.0  |
| 1469 | 2014-09-15 16:35:46 | 2.5.2  |
| 1470 | 2014-09-15 16:52:58 | 2.5.2  |
| 1471 | 2014-09-15 17:14:47 | 2.5.2  |
| 1472 | 2014-09-15 17:52:59 | 2.5.3  |
| 1473 | 2014-09-16 09:51:59 | 2.5.3  |
| 1474 | 2014-09-16 09:53:16 | 2.5.3  |
| 1506 | 2014-09-16 10:36:45 | 2.5.3  |
                  ...
                  ...

我想要的是检查ver_fw中的任何更改并仅选择此行:

--Correct results
+------+---------------------+--------+
| id   | timestamp           | ver_fw |
+------+---------------------+--------+
| 4    | 2014-07-08 18:02:22 | 2.4.19 | 
| 813  | 2014-09-10 11:24:01 | 2.5.0  | 
| 1469 | 2014-09-15 16:35:46 | 2.5.2  | 
| 1472 | 2014-09-15 17:52:59 | 2.5.3  | 
| 1543 | 2014-09-16 15:28:18 | 2.5.4  | 
| 1551 | 2014-09-17 11:37:12 | 2.4.19 |     
| 1555 | 2014-09-18 12:11:04 | 2.5.0  | 
| 1557 | 2014-09-18 13:59:22 | 2.5.4  | 
| 1563 | 2014-09-18 14:43:22 | 2.5.5  | 
| 1637 | 2014-09-23 15:42:07 | 2.5.6  | 
| 1660 | 2014-09-24 10:21:42 | 2.5.7  | 
| 1682 | 2014-09-25 14:51:20 | 2.5.8  | 
| 1692 | 2014-09-26 10:38:39 | 2.4.19 |     
| 5290 | 2015-04-08 20:11:38 | 2.4.81 |
+------+---------------------+--------+

我试图改变我的查询,就像在同一个问题中回答一样,但我失败了:

SELECT 
    id,
    TIMESTAMP,
    @prev_ver := ver_fw ver_fw
FROM tbl_geodata, (SELECT @prev_ver := -1)s
WHERE imei LIKE  '353227026533507' AND @prev_ver != tbl_geodata.ver_fw

结果:

--Incorrect results
+------+---------------------+--------+
| id   | TIMESTAMP           | ver_fw |
+------+---------------------+--------+
|    4 | 2014-07-08 18:02:22 | 2.4.19 |
|  813 | 2014-09-10 11:24:01 | 2.5.0  |
| 1551 | 2014-09-17 11:37:12 | 2.4.19 |
| 1555 | 2014-09-18 12:11:04 | 2.5.0  |
| 1692 | 2014-09-26 10:38:39 | 2.4.19 |
+------+---------------------+--------+

不幸的是,我无法理解一个原因。如何才能获得值与以前相同的行?

P.S。对不起我的英文。

2 个答案:

答案 0 :(得分:4)

以下是使用变量的方法:

SELECT id, `timestamp`, ver_fw
FROM (
  SELECT id, `timestamp`, ver_fw,
         IF ( @prev_ver <> ver_fw, 
             IF (@prev_ver := ver_fw, 1, 1),
             IF (@prev_ver := ver_fw, 0, 0)) AS IsDifferent
  FROM tbl_geodata
  CROSS JOIN (SELECT @prev_ver := '-1') AS var
  WHERE imei LIKE '353227026533507'
  ORDER BY `timestamp` ) t
WHERE IsDifferent = 1
ORDER BY `timestamp`

第一级IF检查不平等。第二级用于分配@prev_ver next 值并返回1 / 0,具体取决于与{{之前值的不等/等式1}}。

Demo here

答案 1 :(得分:0)

使用变量获取先前的值比应该更具挑战性。

幸运的是,如果您在tbl_geodata(timestamp)上有索引(如果定义了排序,则为id),您可以使用相关子查询获得良好的性能:

select gd.*,
       (select gd2.ver_fw
        from tbl_geodata gd2
        where gd2.timestamp < gd.timestamp <-- id might also be used here
        order by gd2.timestamp desc
        limit 1
       ) as prev_ver_fw
from tbl_geodata gd
having prev_ver_fw is null or prev_ver_fw <> ver_fw;

请注意,这使用having子句而不使用group by来使用MySQL扩展。这为最终条件节省了额外的子查询层。