I created a table with following data as per your input
CREATE TABLE data (
"id" INTEGER,
"timestamp" DATE,
"attribute1" VARCHAR(1),
"attribute2" VARCHAR(1)
);
INSERT INTO data
("id", "timestamp", "attribute1", "attribute2")
VALUES
('1', '2021-08-12', null, 'A'),
('1', '2021-08-13', 'B', null),
('2', '2021-08-12', null, 'A'),
('2', '2021-08-13', 'C', 'B'),
('2', '2021-08-14', 'B', null),
('3', '2021-08-12', 'B', null),
('3', '2021-08-14', 'C', 'C');
I think you can achieve your result by aggregating data and picking the first result in that:
SELECT
id, MAX(timestamp) AS timestamp_max,
(array_remove(array_agg(attribute1 ORDER BY timestamp DESC), NULL))[1] AS attribute1_agg,
(array_remove(array_agg(attribute2 ORDER BY timestamp DESC), NULL))[1] AS attribute1_agg
FROM data
GROUP BY id
ORDER BY id ASC;
which gives this output:
| id |
timestamp_max |
attribute1_agg |
attribute1_agg |
| 1 |
2021-08-13T00:00:00.000Z |
B |
A |
| 2 |
2021-08-14T00:00:00.000Z |
B |
B |
| 3 |
2021-08-14T00:00:00.000Z |
C |
C |