Search code examples
sqlsql-servert-sqlwindow-functionsrow-number

Getting the First and Last Row Using ROW_NUMBER and PARTITION BY


Sample Input

Name | Value | Timestamp
-----|-------|-----------------
One  | 1     | 2016-01-01 02:00
Two  | 3     | 2016-01-01 03:00
One  | 2     | 2016-01-02 02:00
Two  | 4     | 2016-01-03 04:00

Desired Output

Name | Value | EarliestTimestamp | LatestTimestamp
-----|-------|-------------------|-----------------
One  | 2     | 2016-01-01 02:00  | 2016-01-02 02:00
Two  | 4     | 2016-01-01 03:00  | 2016-01-03 04:00

Attempted Query

I am trying to use ROW_NUMBER() and PARTITION BY to get the latest Name and Value but I would also like the earliest and latest Timestamp value:

SELECT
    t.Name,
    t.Value,
    t.????????? AS EarliestTimestamp,
    t.Timestamp AS LatestTimestamp
FROM 
    (SELECT
        ROW_NUMBER() OVER (PARTITION BY Name ORDER BY TIMESTAMP DESC) AS RowNumber,
        Name,
        Value
        Timestamp) t
WHERE t.RowNumber = 1

Solution

  • This can be done using window functions min and max.

    select distinct name, 
    min(timestamp) over(partition by name), max(timestamp) over(partition by name)
    from tablename
    

    Example

    Edit: Based on the comments

    select t.name,t.value,t1.earliest,t1.latest
    from t 
    join (select distinct name, 
          min(tm) over(partition by name) earliest, max(tm) over(partition by name) latest
          from t) t1 on t1.name = t.name and t1.latest = t.tm
    

    Edit: Another approach is using the first_value window function, which would eliminate the need for a sub-query and join.

    select distinct
    name, 
    first_value(value) over(partition by name order by timestamp desc) as latest_value,
    min(tm) over(partition by name) earliest,
    -- or first_value can be used 
    -- first_value(timestamp) over(partition by name order by timestamp)
    max(tm) over(partition by name) latest
    -- or first_value can be used
    -- first_value(timestamp) over(partition by name order by timestamp desc)
    from t