Доброго времени суток
Есть следующая таблица:
--
-- Структура таблицы `data`
--
CREATE TABLE IF NOT EXISTS `data` (
`id` int(11) NOT NULL AUTO_INCREMENT, /* ID записи */
`station_id` int(11) NOT NULL, /* ID измерительной станции */
`box_id` int(11) NOT NULL, /* ID измерительного блока на станции */
`param_id` int(11) NOT NULL, /* Код измеренного параметра */
`value` int(11) NOT NULL, /* Значение измеренного параметра */
`tm` bigint(20) NOT NULL, /* Метка времени, когда был получен измеренный параметр */
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Если кратко, то таблица хранит измерения неких параметров (целые числа value
) для нескольких станций station_id
измерения параметров. Внутри станции может быть несколько измерительных блоков box_id
, и параметры они меряют тоже разные - param_id
. Про получении данных записывается время в tm
.
Записи могут быть примерно вот такими:
id station_id box_id param_id value tm
906616 2 1 5 2100 1500270962
906616 2 2 2 2199 1500270960
906616 2 3 3 2850 1500270960
Ну и подобный числовой хаос, который без поллитры не понятен. Тем не менее каждая запись важна, и по ним строятся всякие графики, отчеты и прочий анализ.
Количество записей в таблице порядка 2-3 миллионов и возрастает. Записи годичной давности вынимаются из этой таблицы и перекладываются в архивные таблицы по ежемесячному cron.
К сути. Измерительное оборудование сгорело. Несколько станций записали в нескольких своих блоках вместо нормальных измерений нули и единицы (а возможно, и что-то еще нехорошее, но никак не похожее на нормальные измерения).
Задача: найти невалидные данные и уничтожить (удалить из таблицы), при этом не задев валидные данные.
Для тех параметров, которые выдают случайные с точки зрения человека данные, это невозможно - тут ничего не попишешь. Но есть параметры, которые имеют определенный закон - проще говоря, постоянно возрастают. Причем возрастают они гарантированно для одного измерительного прибора - то есть если взять
SELECT `value` FROM `data` WHERE `station_id` = 1,`box_id` = 1,`param_id` = 1 ORDER BY `tm` DESC;
то value
будет отсортированным массивом (если данные валидны). Но это не так по факту - есть вкрапления невалидных данных
Вот собственно и суть вопроса, по которому я обращаюсь. Нужно сочинить такой SQL запрос, который сумеет выбрать все записи с определенным значением индекса [station_id
,box_id
,param_id
], у которых начался сбой - то есть значение A
.value
стало меньше чем B
.value
, при этом A
.tm
больше B
.tm
, то есть значение было получено позже и уменьшилось относительно предыдущего.
Умом я понимаю, что нужно сделать. Есть рабочее решение на PHP, которые выбирает блок измерений, который может прожевать, и в коде смотрит, все ли в порядке, удаляя невалидные данные. Недостаток этого решение в длительности обработки и в необходимости лопатить все данные, вместо только нужных участков. Второй недостаток - данные постоянно пополняются, и нет уверенности в определенный момент времени, что таблица очищена от сбоев, поскольку скрипт может обработать только небольшую часть данных. Нельзя сказать, что если скрипт ничего не сделал, то данные валидны и возрастают - потому что скрипт не может охватить все данные сразу, а только небольшое окно от сих до сих. На мой взгляд для этого как раз нужен SQL.
Результатом работы SQL запроса я вижу id
записей, в которых обнаружен сбой. Если таких записей нет и запрос вернул пустоту, значит вся таблица валидна и сбоев нет. Можно убрать поллитру и открыть шампанское.
Я не силен в сочинении сложных SQL, обычно хватает маленьких. Сам язык знаю на базовом уровне - выборка из двух-трех таблиц, вставка, удаление. Но тут совсем необычная ситуация обработки данных.
Решение в лоб:
SELECT t1.id
FROM data t1 JOIN data t2
ON (t1.tm<t2.tm AND t1.value>t2.value)
WHERE t1.station_id = 1 AND t1.box_id = 1 AND t1.param_id = 1 AND t2.station_id = 1 AND t2.box_id = 1 AND t2.param_id = 1;
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Виртуальный выделенный сервер (VDS) становится отличным выбором
Существует ли возможность создания триггера для MariaDB или MySQL, который бы выполнялся с определённой периодичностьюНапример, удалял записи...
Хочу перенести сайт WordPress на другой доменЭкспортировал базу данных WordPress в phpMyAdmin, изменил домен и имя базы данных, хочу импортировать базу...