Mysql
 sql >> Base de données >  >> RDS >> Mysql

Filtrer l'ensemble de résultats de la requête MySQL pour générer plusieurs occurrences dans une période de temps spécifique

Si nous voulons filtrer les lignes où il n'y a pas au moins quatre lignes précédentes au cours des 60 dernières secondes, en supposant que dateTimeOrigination est de type entier, un horodatage de style Unix 32 bits, nous pouvons faire quelque chose comme ceci :

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

REMARQUE :Pour des raisons de performances, nous préférons avoir des prédicats sur des colonnes nues.

Avec un formulaire comme celui-ci, avec la colonne entourée d'une expression :

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

MySQL évaluera la fonction pour chaque ligne dans le tableau, puis comparez le retour de la fonction au littéral.

Avec un formulaire comme celui-ci :

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

MySQL évaluera les expressions du côté droit un temps, sous forme de littéraux . Ce qui permet à MySQL d'utiliser efficacement une opération d'analyse de plage sur un index approprié.

SUIVI

Pour de meilleures performances de la requête externe, le meilleur index serait probablement un index avec une colonne de début de dateTimeOrigination, contenant de préférence

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

Pour de meilleures performances, un index de couverture, pour éviter les recherches sur les pages de la table sous-jacente. Par exemple :

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

Avec cela, nous nous attendrions à ce qu'EXPLAIN affiche "Utilisation de l'index".

Pour la sous-requête corrélée, nous voudrions un index avec des colonnes principales comme ceci :

... ON cdr_records (originalCalledPartyNumber,dateTimeOrigination)

Je vous recommande fortement de regarder la sortie d'EXPLAIN pour voir quels index MySQL utilise pour la requête.