Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Filtrando o conjunto de resultados da consulta MySQL para gerar várias ocorrências dentro de um período de tempo específico


Se quisermos filtrar as linhas onde não há pelo menos quatro linhas anteriores nos últimos 60 segundos, supondo que dateTimeOrigination seja do tipo inteiro, um carimbo de data/hora no estilo unix de 32 bits, podemos fazer algo assim:
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

NOTA:Para desempenho, preferimos ter predicados em colunas nuas.

Com um formulário como este, com a coluna envolvida em uma expressão:
 WHERE FROM_UNIXTIME(r.dateTimeOrigination) LIKE '2016-05-20%'

O MySQL avaliará a função para cada linha na tabela e, em seguida, compare o retorno da função com o literal.

Com um formulário como este:
 WHERE r.dateTimeOrigination >= UNIX_TIMESTAMP('2016-05-20')
   AND r.dateTimeOrigination  < UNIX_TIMESTAMP('2016-05-21')

O MySQL avaliará as expressões do lado direito um tempo, como literais . O que permite que o MySQL faça uso efetivo de uma operação de varredura de intervalo em um índice adequado.

ACOMPANHAMENTO

Para melhor desempenho da consulta externa, o melhor índice provavelmente seria um índice com coluna inicial de dateTimeOrigination, de preferência contendo
... ON cdr_records (dateTimeOrigination
    ,callingPartyNumber,originalCalledPartyNumber,finalCalledPartyNumber)

Para melhor desempenho, um índice de cobertura, para evitar pesquisas nas páginas da tabela subjacente. Por exemplo:
... ON cdr_records (dateTimeOrigination
    ,callingPartyNumber,originalCalledPartyNumber,finalCalledPartyNumber
    ,duration,origDeviceName,destDeviceName)

Com isso, esperamos que EXPLAIN mostre "Usando índice".

Para a subconsulta correlacionada, gostaríamos de um índice com colunas iniciais como esta:
... ON cdr_records (originalCalledPartyNumber,dateTimeOrigination)

Eu recomendo fortemente que você veja a saída de EXPLAIN para ver quais índices o MySQL está usando para a consulta.