Описание проблемы. У меня есть следующий запрос для получения последних предупреждений за последние 15 минут.
SELECT
AlmCode,OccurTime,ClearTime....columnN
FROM
TB_ALM
WHERE
AlmCode IN ('3236',....'5978') AND
OccurTime >= date_sub(NOW(),interval 15 minute);
Структура таблицы:
CREATE TABLE `TB_ALM` (
`Col1` smallint(2) DEFAULT NULL,
`Col2` int(4) DEFAULT NULL,
`Col3` int(2) DEFAULT NULL,
`Col4` int(10) DEFAULT NULL,
`Col5` int(10) unsigned DEFAULT NULL,
`Col6` int(2) DEFAULT NULL,
`Col7` int(2) DEFAULT NULL,
`Col8` int(10) DEFAULT NULL,
`Col9` int(10) unsigned DEFAULT NULL,
`AlmCode` int(10) unsigned DEFAULT NULL,
`Col10` int(2) NOT NULL,
`Col11` int(10) unsigned DEFAULT NULL,
`Col12` char(12) DEFAULT NULL,
`Col13` int(2) unsigned DEFAULT NULL,
`Col14` int(10) unsigned DEFAULT NULL,
`Col15` int(10) unsigned DEFAULT NULL,
`Col16` int(10) unsigned DEFAULT NULL,
`OccurTime` datetime NOT NULL,
`ClearTime` datetime DEFAULT NULL,
`AlmDesc` varchar(500) DEFAULT NULL,
`Col20` int(1) DEFAULT '0',
`Col21` bigint(20) DEFAULT NULL,
`Col22` char(120) DEFAULT NULL,
`Col23` int(10) DEFAULT NULL,
KEY `TB_ALM_IDX2` (`Col1`,`Col2`,`Col3`,`Col6`,`Col7`,`Col11`,`AlmCode`,`Col9`,`Col4`,`Col8`,`ClearTime`) USING BTREE,
KEY `TB_ALM_IDX1` (`Col1`,`Col2`,`Col3`,`Col6`,`Col7`,`Col11`,`AlmCode`,`Col5`,`Col21`),
KEY `TB_ALM_IDX3` (`Col1`,`Col2`,`Col3`,`Col5`) USING BTREE,
KEY `TB_ALM_IDX4` (`Col1`,`Col2`,`Col3`,`OccurTime`,`ClearTime`,`Col21`) USING BTREE,
KEY `TB_ALM_IDX5` (`Col23`),
KEY `TB_ALM_IDX6` (`Col1`,`Col2`,`Col3`,`Col6`,`Col7`,`AlmCode`,`Col11`,`ClearTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Что нужно: Теперь я хочу изменить это, чтобы получать сигналы тревоги со следующими критериями:
а. Тревоги (AlmCodes) возникли за последние 15 минут (исходное требование) И
б. ТОЛЬКО если каждый из аварийных сигналов (кодов аварийных сигналов) не возникал более трех раз в любом из 15-минутных окон в течение последних шести часов.
Что пробовали. Я попробовал следующий подход:
Получите DISTINCT(AlmCodes) за последние 15 минут.
выберите отдельный (AlmCode) из TB_ALM, где AlmCode IN ('3236','4002','4008','4036','4050','4051','4102','4108','4136','4150' ,'4151','4202','4208','4236','4250','4251','4801','4802','4836','4848','4850','4851',' 4902", "4936", "4950", "4951", "5002", "5008", "5036", "5050", "5051", "5102", "5108", "5136", "5150" ,'5151','5202','5208','5236','5250','5251','5947','5950','5952','5975','5976','5977',' 5978') AND OccurTime >= date_sub(NOW(),интервал 15 минут);
Используйте Item-1 (выше) в качестве подзапроса и получите количество вхождений для каждого AlmCode.
выберите Almcode,concat(date(OccurTime),' ',HOUR(OccurTime)) как HR,count(*) из TB_ALM_HISTORY, где AlmCode IN (выберите отдельный(s.AlmCode) из TB_ALM_HISTORY s, где s.AlmCode IN ('3236' ,'4002','4008','4036','4050','4051','4102','4108','4136','4150','4151','4202','4208',' 4236", "4250", "4251", "4801", "4802", "4836", "4848", "4850", "4851", "4902", "4936", "4950", "4951" ,'5002','5008','5036','5050','5051','5102','5108','5136','5150','5151','5202','5208',' 5236','5250','5251','5947','5950','5952','5975','5976','5977','5978') И s.OccurTime >= date_sub(NOW() ,интервал 15 минут) ) AND OccurTime >= date_sub(NOW(),интервал 15*4*24 минуты) группа по AlmCode,HR;
Проблемы:
- Запрос Items-2 продолжает выполняться всегда с (подзапросом), где, как если бы я запускал их как два отдельных запроса, он мгновенно возвращается, как показано ниже. Чего здесь не хватает?
Запрос-1: Получить уникальные сигналы тревоги
select distinct(AlmCode)
from TB_ALM_HISTORY
where AlmCode IN ('3236','4002','4008','4036','4050','4051','4102','4108','4136','4150','4151','4202','4208','4236','4250','4251','4801','4802','4836','4848','4850','4851','4902','4936','4950','4951','5002','5008','5036','5050','5051','5102','5108','5136','5150','5151','5202','5208','5236','5250','5251','5947','5950','5952','5975','5976','5977','5978')
AND OccurTime >= date_sub(NOW(),interval 15 minute) ;
+---------+
| AlmCode |
+---------+
| 3236 |
| 5202 |
| 5236 |
+---------+
Запрос-2: получить количество для каждого уникального будильника за последние 6 часов.
select Almcode,concat(date(OccurTime),' ',LPAD(HOUR(OccurTime),2,'0')) as HR,count(*) from TB_ALM_HISTORY where AlmCode IN ('3236','5202','5236') AND OccurTime >= date_sub(NOW(),interval 15*4*7 minute) group by AlmCode,HR;
+---------+---------------+----------+
| Almcode | HR | count(*) |
+---------+---------------+----------+
| 3236 | 2015-08-04 11 | 2 |
| 5202 | 2015-08-04 13 | 6 |
| 5202 | 2015-08-04 14 | 4 |
| 5202 | 2015-08-04 15 | 2 |
| 5202 | 2015-08-04 16 | 1 |
| 5202 | 2015-08-04 17 | 2 |
+---------+---------------+----------+
Если предположить, что этот запрос был запущен в 18:00 по восточному стандартному времени, код AlmCode 5202 возник за последние 6 часов (между 12–18 часами), и, следовательно, результаты для этого кода AlmCode не должны включаться в окончательный запрос на выборку (или за последние 15 минут). в то время как код AlmCode 3236 не возникал в течение последних 6 часов, и, следовательно, должны быть включены все аварийные сигналы, возникшие за последние 15 минут для данного конкретного кода AlmCode.
- Как получить конечный результат в одном запросе?
а. Получите уникальный AlmCode с OccurTime >= Last 15 Minutes
б. Для каждого из этих AlmCode проверьте, произошло ли это трижды за последние 6 часов.
в. Если НЕТ, извлеките все сигналы тревоги для этого AlmCode с OccurTime >= Last 15 Minutes (если ДА, не включайте и просто пропустите)