I got a bit rusty with SQL.
Lets say I have tblMachineLogs
with MachineLogID
, MachineID
, LogTime (date+time)
.
This table is filled with logs from 10 machines with MachineID
1 to 10 and have lots of rows in it.
I want to select for example the last 5 log events but of each machine.
Thanks in advance
Use
Window Function
which will help you to find last5
log events
in each group(MachineID)
Solution for SQL Server. I tested it on SQL Server 2008.
Imagine that
MachineLogs
has millions or billions of rows and it has index on(MachineID, LogTime DESC)
. Solution withROW_NUMBER
would scan the whole table (or just the index, but it will be a full scan). If the index is on(MachineID, LogTime ASC)
it would do an extra expensive sort as well.On the other hand, if we have a tiny table
Machines
with 10 rows, one for eachMachineID
, then it is possible to write a query that does 10 seeks on the index instead of scanning the whole big table.I'll create a big table
MachineLogs
with 1 million rows and small tableMachines
with 10 rows and test two solutions.Table
Machines
will have 10 rows:Big table with index on
([MachineID] ASC, [LogTime] DESC)
:Generate 1M rows:
Solution with ROW_NUMBER
Solution with CROSS APPLY
Execution plans
You can see that solution with
ROW_NUMBER
does a index scan and solution withCROSS APPLY
does index seek.IO statistics
Solution with
ROW_NUMBER
:Solution with
CROSS APPLY
:To keep it simple, I'd do it with an individual query per machine.
If you are using MySQL:
That would return the last 5 event log items from machine with ID indicated by
str_machineid
. Remove quotes if machine ID is a numeric field (and it should).Create a query for each machine that selects the top 5 rows, union it all and sort by the log time in a descending order (to get the last 5). Here is an example for two machines, just fill the missing 8.