1

I have a table that has has some measurements, ID and date.

The table is built like so

ID     DATE    M1    M2
1      2020     1    NULL
1      2020    NULL   15
1      2018     2    NULL
2      2019     1    NULL
2      2019    NULL   1

I would like to end up with a table that has one row per ID with the most recent measurement

ID M1 M2
1  1  15
2  1   1

Any ideas?

Uwe Allner
  • 3,399
  • 9
  • 35
  • 49
Edi Itelman
  • 423
  • 5
  • 14
  • 1
    Which DBMS product are you using? "SQL" is just a query language, not the name of a specific database product. Please add a [tag](https://stackoverflow.com/help/tagging) for the database product you are using. [Why should I tag my DBMS](https://meta.stackoverflow.com/questions/388759/) –  Apr 07 '20 at 11:54

3 Answers3

1

You can use correlated sub-query with aggregation :

select id, max(m1), max(m2)
from t 
where t.date = (select max(t1.date) from t t1 where t1.id = t.id)
group by id;
Yogesh Sharma
  • 49,870
  • 5
  • 26
  • 52
0

Use ROW_NUMBER combined with an aggregation:

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DATE DESC) rn
    FROM yourTable
)

SELECT ID, MAX(M1) AS M1, MAX(M2) AS M2
FROM cte
WHERE rn = 1
GROUP BY ID;

The row number lets us restrict to only records for each ID having the most recent year date. Then, we aggregate to find the max values for M1 and M2.

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
0

In standard SQL, you can use lag(ignore nulls):

select id, coalesce(m1, prev_m1), coalesce(m2, prev_m2)
from (select t.*, 
             lag(m1 ignore nulls) over (partition by id order by date) as prev_m1,
            lag(m2 ignore nulls) over (partition by id order by date) as prev_m2,
             row_number() over (partition by id order by date desc) as seqnum
      from t
     ) t
where seqnum = 1;
Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786