Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Filtern der Ergebnismenge von MySQL-Abfragen, um mehrere Vorkommen innerhalb eines bestimmten Zeitraums zu erhalten

Wenn wir die Zeilen herausfiltern möchten, in denen es nicht mindestens vier vorangegangene Zeilen innerhalb der letzten 60 Sekunden gibt, können wir unter der Annahme, dass dateTimeOrigination vom Typ Integer ist, ein 32-Bit-Zeitstempel im Unix-Stil, Folgendes tun:

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

HINWEIS:Aus Leistungsgründen bevorzugen wir Prädikate für leere Spalten.

Bei einem Formular wie diesem, bei dem die Spalte in einen Ausdruck eingeschlossen ist:

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

MySQL wertet die Funktion für alle aus Zeile in der Tabelle und vergleichen Sie dann die Rückgabe der Funktion mit dem Literal.

Mit einem Formular wie diesem:

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

MySQL wertet die Ausdrücke auf der rechten Seite eins aus Zeit, als Literale . Dadurch kann MySQL eine Range-Scan-Operation für einen geeigneten Index effektiv nutzen.

NACHVERFOLGUNG

Für die beste Leistung der äußeren Abfrage wäre der beste Index wahrscheinlich ein Index mit der führenden Spalte dateTimeOrigination, der vorzugsweise

enthält
... ON cdr_records (dateTimeOrigination
    ,callingPartyNumber,originalCalledPartyNumber,finalCalledPartyNumber)

Für die beste Leistung einen abdeckenden Index, um Suchen auf den Seiten in der zugrunde liegenden Tabelle zu vermeiden. Zum Beispiel:

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

Damit würden wir erwarten, dass EXPLAIN "Using index" anzeigt.

Für die korrelierte Unterabfrage möchten wir einen Index mit führenden Spalten wie dieser:

... ON cdr_records (originalCalledPartyNumber,dateTimeOrigination)

Ich empfehle Ihnen dringend, sich die Ausgabe von EXPLAIN anzusehen, um zu sehen, welche Indizes MySQL für die Abfrage verwendet.