我有一个表格,其中以一定的时间间隔收集来自传感器的数据(例如温度)。
其中一些数据很少更改,因此连续的行仅 ID 不同。
我希望能够找到这些行并删除重复项,只留下具有相同数据的最旧和最年轻的行。
目前我是这样做的:
SELECT
m.statistic_id
, c.id
FROM statistics_meta AS m
INNER JOIN statistics AS c ON c.metadata_id = m.id
INNER JOIN statistics AS p ON p.id = (SELECT MAX(t.id) FROM statistics AS t WHERE t.metadata_id = m.id AND t.id < c.id)
INNER JOIN statistics AS n ON n.id = (SELECT MIN(t.id) FROM statistics AS t WHERE t.metadata_id = m.id AND t.id > c.id)
WHERE IFNULL(c.state, 0) = IFNULL(p.state, 0)
AND IFNULL(c.state, 0) = IFNULL(n.state, 0)
*
c
- 当前行,p
- 上一行,n
- 下一行
不幸的是,这个查询需要很长时间,并且随着新行的出现,它会花费更长的时间。
怎样才能做得更好?
你谈论了id和温度,但我发现你的SQL很难与这些数量联系起来,因为你有表
statistics
和statistics_meta
以及各种列id
,statistic_id
,metadata_id
和state
,没有这些表和列的描述。请参阅提出良好的结构化查询语言 (SQL) 问题的提示。因此,我将解决一些我能理解的问题,也许您可以将其与您的问题联系起来:
假设您有一个表
measurement
,其中有两列:id
和temperature
,那么下面的SQL可能比您所实现的更高效;你必须尝试一下才能看到。这个想法是,如果您有一行包含一些 id
值 ID 和 temperature
值 T,那么如果前两行(即 id
值 ID-1 和 ID-2)具有相同的 temperature
值您可以安全地删除 id
值 ID-1 的行。因此,我们创建一个子查询来计算要删除的行,然后按如下方式执行删除:
/* create table */
create table measurement (
id int primary key,
temperature int
);
/* create some sample data */
insert into measurement(id, temperature) values
(1, 72),
(2, 75),
(3, 75),
(4, 77),
(5, 77),
(6, 77),
(7, 77),
(8, 78),
(9, 78),
(10, 78),
(11, 79)
;
/* delete the rows */
delete from measurement where id in (
select id - 1 from measurement m
where temperature = (select temperature from measurement where id = m.id - 1)
and temperature = (select temperature from measurement where id = m.id -2)
);
/* redisplay table after deletion */
select * from measurement;
显示:
id temperature
-- -----------
1 72
2 75
3 75
4 77
7 77
8 78
10 78
11 79