我在这里发现了一个标题完全相同的非常相似的问题:Mysql,检查字段值更改?,但它并不完全是我所需要的。
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 |
+------+---------------------+--------+
不幸的是,我无法理解原因。如何仅获取值与以前更改的行?
附言对不起我的英语。
以下是使用变量执行此操作的方法:
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
其下一个值并返回 1
/0
,具体取决于ver_fw
的不等式/相等。
在这里演示
使用变量获取以前的值比它应该更具挑战性。
幸运的是,如果你有一个索引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;
请注意,这通过使用没有group by
的 having
子句来使用 MySQL 扩展。 这为最终条件节省了额外的子查询层。