Sql-server – Get a column from the latest row by another column

greatest-n-per-groupgroup bysql server

Take a look at this sqlfiddle. I have a table that contains history of records for another table(irrelevant, foreign key included). Each history item will contain a status and time fields. I want to write a select statement that would give me a list of unique(by foreign key) histories with the latest status.

From other searches I think what I need is

SELECT MAX(created) as created, originalMsgId 
from ReplayHistory 
group by originalMsgId
created             Id
------------------------
2018-06-22 19:18:43 11
2018-06-22 09:28:43 12

but it doesn't return the column I need; status.

The query I am using is

SELECT MAX(created) as created, originalMsgId, status 
from ReplayHistory 
group by originalMsgId, status

which returns me

created              Id  status
----------------------------------
2018-06-22 19:18:43  11  Finished
2018-06-22 19:17:43  11  InProgress
2018-06-22 09:28:43  12  InProgress
2018-06-22 19:16:43  11  NotStarted
2018-06-22 09:27:43  12  NotStarted

I know that this is happening because of group by status, but if I need it in select then I have to keep it in group by.

Best Answer

This is a good use for a window function, row_number()

select 
   x.created, 
   x.OriginalMsgId, 
   x.Status
from (SELECT 
         RN = row_number() over (partition by r.originalMsgId order by Created desc), 
         r.originalMsgId, 
         r.status, 
         created 
      from ReplayHistory r) x
where x.RN = 1

Another way is using MAX with a derived table.

SELECT 
   r.originalMsgId, 
   r.status, 
   r.created 
from ReplayHistory r
inner join
    (select originalMsgId, max(created) dt from ReplayHistory group by originalMsgId) x on
    x.dt = r.created 
    and x.originalMsgId = r.originalMsgId

Notes on performance