sql >> Database >  >> RDS >> Mysql

Het filteren van MySQL-queryresultaten om meerdere gebeurtenissen binnen een bepaalde tijdsperiode op te leveren

Als we de rijen willen uitfilteren waar er niet ten minste vier voorgaande rijen zijn in de afgelopen 60 seconden, ervan uitgaande dat dateTimeOrigination een geheel getal is, een 32-bits Unix-stijl tijdstempel, kunnen we zoiets als dit doen:

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

OPMERKING:voor prestaties geven we er de voorkeur aan predikaten op kale kolommen te hebben.

Met een formulier als dit, met de kolom verpakt in een uitdrukking:

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

MySQL evalueert de functie voor elke rij in de tabel en vergelijk vervolgens het resultaat van de functie met de letterlijke.

Met een formulier als dit:

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

MySQL evalueert de uitdrukkingen aan de rechterkant één tijd, als letterlijk . Waardoor MySQL effectief gebruik kan maken van een bereikscanbewerking op een geschikte index.

VERVOLG

Voor de beste prestaties van de buitenste query is de beste index waarschijnlijk een index met een leidende kolom van dateTimeOrigination, bij voorkeur met

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

Voor de beste prestaties, een dekkende index, om lookups naar de pagina's in de onderliggende tabel te voorkomen. Bijvoorbeeld:

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

Daarmee verwachten we dat EXPLAIN "Using index" laat zien.

Voor de gecorreleerde subquery willen we een index met voorloopkolommen zoals deze:

... ON cdr_records (originalCalledPartyNumber,dateTimeOrigination)

Ik raad je ten zeerste aan om naar de uitvoer van EXPLAIN te kijken om te zien welke indexen MySQL voor de query gebruikt.




  1. Waarom kan een nieuwe gebruiker in PostgreSQL verbinding maken met alle databases?

  2. MySQL-server opstartfout 'De server is gestopt zonder het PID-bestand bij te werken'

  3. Wat is het gedrag van de min-operator tussen twee datetimes in MySQL?

  4. Probleem met veel databases?