I have 2 tables that I'm trying to query. The first has a list of meters. The second, has the data for those meters. I want to get the newest reading for each meter.
Originally, this was in a group by statement, but it ended up processing all 7 million rows in our database, and took a little over a second. A subquery and a number of other ways of writing it had the same result.
I have a clustered index that covers the EndTime and the MeterDataConfigurationId columns in the MeterRecordings table.
Ultimately, this is what I wrote, which performs in about 20 milliseconds. It seems like SQL should be smart enough to perform the "group by" query in the same time.
Declare @Meters Table
(
MeterId Integer,
LastValue float,
LastTimestamp DateTime
)
Declare MeterCursor Cursor For
Select Id
From MeterDataConfiguration
Declare @MeterId Int
Open MeterCursor
Fetch Next From MeterCursor Into @MeterId
While @@FETCH_STATUS = 0
Begin
Declare @LastValue int
Declare @LastTimestamp DateTime
Select @LastValue = mr.DataValue, @LastTimestamp = mr.EndTime
From MeterRecording mr
Where mr.MeterDataConfigurationId = @MeterId
And mr.EndTime = (Select MAX(EndTime) from MeterRecording mr2 Where mr2.MeterDataConfigurationId = @MeterId)
Insert Into @Meters
Select @MeterId, @LastValue, @LastTimestamp
Fetch Next From MeterCursor Into @MeterId
End
Deallocate MeterCursor
Select *
From @Meters
Here is an example of the same query that performs horribly:
select mdc.id, mr.EndTime
from MeterDataConfiguration mdc
inner join MeterRecording mr on
mr.MeterDataConfigurationId = mdc.Id
and mr.EndTime = (select MAX(EndTime) from MeterRecording mr2 where MeterDataConfigurationId = mdc.Id)