过滤MySQL查询结果集以在特定时间段内产生多个出现

时间:2016-05-21 16:19:58

标签: mysql sql

如果这是一个常见的问题,请提前道歉,我尝试研究它,但似乎找不到合适的东西。

我有一个查询以我喜欢的方式提取数据但想添加一个参数,该参数只会告诉我在60秒内出现5次或更多次的值;

select from_unixtime(dateTimeOrigination), callingPartyNumber,
        originalCalledPartyNumber, finalCalledPartyNumber, duration, origDeviceName, destDeviceName
 from cdr_records
 where (from_unixtime(dateTimeOrigination) like '2016-05-20%') and 
       (callingPartyNumber not like 'b00%') and
       (originalCalledPartyNumber not like 'b00%') and 
       (finalCalledPartyNumber not like 'b00%')
 order by originalCalledPartyNumber, dateTimeOrigination;

此查询已经过滤了指定日期的结果,并按照我喜欢的方式对结果进行排序,但它会提取所有内容。有人可以告诉我怎么说,"只告诉我有关originalCalledPartyNumber的价值,如果它在任何60秒的时间段内出现5次或更多,就告诉我。"?

1 个答案:

答案 0 :(得分:1)

如果我们要过滤掉过去60秒内至少有前四行的行,假设dateTimeOrigination是整数类型,一个32位的unix样式时间戳,我们可以这样做:

SELECT FROM_UNIXTIME(r.dateTimeOrigination) AS dateTimeOrigination
     , r.callingPartyNumber
     , r.originalCalledPartyNumber
     , r.finalCalledPartyNumber
     , r.duration
     , r.origDeviceName
     , r.destDeviceName
  FROM cdr_records r
 WHERE r.dateTimeOrigination >= UNIX_TIMESTAMP('2016-05-20')
   AND r.dateTimeOrigination  < UNIX_TIMESTAMP('2016-05-21')
   AND r.callingPartyNumber NOT LIKE 'b00%'
   AND r.originalCalledPartyNumber NOT LIKE 'b00%'
   AND r.finalCalledPartyNumber NOT LIKE 'b00%'

   AND ( SELECT COUNT(1)
           FROM cdr_records c
          WHERE c.originalCalledPartyNumber = r.originalCalledPartyNumber
            AND c.dateTimeOrigination       > r.dateTimeOrigination - 60
            AND c.dateTimeOrigination      <= r.dateTimeOrigination
       ) > 4

 ORDER
    BY r.originalCalledPartyNumber
     , r.dateTimeOrigination

注意:为了提高性能,我们更喜欢在裸列上使用谓词。

使用这样的表单,将列包装在表达式中:

 WHERE FROM_UNIXTIME(r.dateTimeOrigination) LIKE '2016-05-20%'

MySQL将评估表中每个行的函数,然后将函数的返回值与文字进行比较。

使用这样的表格:

 WHERE r.dateTimeOrigination >= UNIX_TIMESTAMP('2016-05-20')
   AND r.dateTimeOrigination  < UNIX_TIMESTAMP('2016-05-21')

MySQL将评估右侧一个时间的表达式,如 literals 。这允许MySQL在合适的索引上有效地使用范围扫描操作。

<强>后续

为了获得外部查询的最佳性能,最佳索引可能是具有dateTimeOrigination前导列的索引,最好包含

... ON cdr_records (dateTimeOrigination
    ,callingPartyNumber,originalCalledPartyNumber,finalCalledPartyNumber)

为了获得最佳性能,请使用覆盖索引,以避免查找基础表中的页面。例如:

... ON cdr_records (dateTimeOrigination
    ,callingPartyNumber,originalCalledPartyNumber,finalCalledPartyNumber
    ,duration,origDeviceName,destDeviceName)

有了这个,我们希望EXPLAIN显示“使用索引”。

对于相关子查询,我们需要一个带有前导列的索引,如下所示:

... ON cdr_records (originalCalledPartyNumber,dateTimeOrigination)

我强烈建议您查看EXPLAIN的输出,以查看MySQL用于查询的索引。