mysql选择具有复杂计数+小时范围标准的列

时间:2015-08-04 20:33:57

标签: mysql subquery hour in-subquery

问题说明: 我有以下查询来检索最近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分钟内发生(原始请求) AND

湾仅在过去六小时内,每个警报(AlmCodes)在15分钟窗口中的任何一个都没有发生过三次以上

尝试了什么: 我尝试了以下方法:

  1. 在过去15分钟内获取DISTINCT(AlmCodes)。

    从TB_ALM中选择不同的(AlmCode),其中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')和OccurTime> = date_sub(NOW(),间隔15分钟);

  2. 使用Item-1(上面)作为子查询,并获取每个AlmCode的出现次数。

    选择Almcode,concat(日期(OccurTime),'',HOUR(OccurTime))作为HR,计数(*)来自TB_ALM_HISTORY,其中AlmCode IN( 从TB_ALM_HISTORY中选择distinct(s.AlmCode),其中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分钟) )和AlmCode,HR的'和OccurTime> = date_sub(NOW(),间隔15 * 4 * 24分钟);

  3. 的问题:

    1. Items-2 Query持续执行(子查询),就好像我将它们作为两个单独的查询运行一样,它会立即返回,如下所示。什么不见​​到这里?
    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 |
      +---------+---------------+----------+
      

      假设此查询在美国东部时间下午6点运行,AlmCode 5202在最近6小时内发生(btwn 12-18小时),因此该AlmCode的结果不应包含在最终选择查询中(最近15分钟内发生)。 而AlmCode 3236在过去的6小时内没有发生,因此必须包含此特定AlmCode在过去15分钟内发生的所有警报。

      1. 如何在一次查询中获得我的结束输出?
      2. 一个。获取具有OccurTime> =最后15分钟的唯一AlmCode

        湾对于这些AlmCode中的每一个,检查它是否在过去6小时内发生了三次

        ℃。 如果否,则使用OccurTime> =最后15分钟拉出此AlmCode的所有警报 (如果是,则不包括&只;跳过)

1 个答案:

答案 0 :(得分:1)

最近15分钟内创建的所有闹钟(您的查询)。

select distinct(AlmCode) 
from TB_ALM 
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) 

所有警报,在过去6小时内任何15分钟内发生三次(之后将被排除在外)

select distinct t1.AlmCode
from TB_ALM t1
inner join TB_ALM t2 on t2.AlmCode = t1.AlmCode 
    and t2.OccurTime <= date_add(t1.OccurTime, interval 15 minute)
    and t2.OccurTime > t1.OccurTime
inner join TB_ALM t3 on t3.AlmCode = t1.AlmCode 
    and t3.OccurTime <= date_add(t1.OccurTime, interval 15 minute)
    and t3.OccurTime > t2.OccurTime
WHERE true
  AND t1.OccurTime >= date_sub(now(), interval 6 hour)
  AND t1.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')

所以最后的查询是

select distinct(AlmCode) 
from TB_ALM 
where true
  AND OccurTime >= date_sub(NOW(),interval 15 minute) 
  AND 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 AlmCode NOT IN (select distinct t1.AlmCode
from TB_ALM t1
inner join TB_ALM t2 on t2.AlmCode = t1.AlmCode 
    and t2.OccurTime <= date_add(t1.OccurTime, interval 15 minute)
    and t2.OccurTime > t1.OccurTime
inner join TB_ALM t3 on t3.AlmCode = t1.AlmCode 
    and t3.OccurTime <= date_add(t1.OccurTime, interval 15 minute)
    and t3.OccurTime > t2.OccurTime
WHERE true
      AND t1.OccurTime >= date_sub(now(), interval 6 hour)
      AND t1.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')
  )

在AlmCode列上添加索引,它将显着缩短执行时间