Search code examples
sqlsql-servert-sqljoinhaving-clause

Selecting records by group each having the max date respectively


I have three tables of concern and a query which generates the following output from them, where each field is prepended by a letter representing the table of origin for demonstration purposes. What I would like instead, is a report with only the most recent data, i.e. I want only the row returned with the MAX(EntryDate), but I can't figure out how to accomplish this. I've tried, HAVING, aggregates, etc, but with no success. Either my approach is wrong, or I'm missing something syntactically.

s.ID    r.FirstID    m.ID   m.PartNum     m.Revision     r.EntryDate
26      42           13     NULL          A              2012-03-25 15:32:00
26      42           17     820044444     B              2012-03-27 09:48:00
26      42           14     820056789     C              2012-03-28 12:19:00

Desired Result:

s.ID    r.FirstID    m.ID   m.PartNum     m.Revision     r.EntryDate
26      42           14     820056789     C              2012-03-28 12:19:00

For a little additional background, the r.FirstID represents a grouping of records all related to each other, so for each grouping I wish to return only the record with the most recent data.

Here is my query that I have so far:

select s.ID,r.FirstID,m.ID,m.PartNum,m.Revision,r.EntryDate from StatusLog s
    left join (select FirstID,PartInfoID from Request where PartInfoID is not null group by FirstID,PartInfoID) r on s.FirstID= r.FirstID
    --required filtering here? Or move this extra join to the inner query?
    left join PartInfo m on r.PartInfoID = m.ID

I'm using SQL Server for my DBMS.


Solution

  • The easiest way will be to use ROW_NUMBER() (and I am using a CTE for simplicity). Let me know if you need me to explain what is happening here :)

    WITH myCTE
    AS
    (
        SELECT s.ID AS sID, r.FirstID, m.ID AS mID, m.PartNum, m.Revision, 
            r.EntryDate, 
            ROW_NUMBER() OVER 
                (PARTITION BY r.FirstID ORDER BY r.EntryDate DESC) AS RowNumber
        FROM StatusLog s
            LEFT JOIN 
            (
                SELECT FirstID, PartInfoID 
                FROM Request 
                WHERE PartInfoID IS NOT NULL 
                GROUP BY FirstID,PartInfoID
            ) AS r 
                ON s.FirstID= r.FirstID
            LEFT JOIN PartInfo m 
                ON r.PartInfoID = m.ID
    )
    SELECT sID,FirstID,mID,PartNum,Revision,EntryDate
    FROM myCTE 
    WHERE RowNumber = 1;