To powinno wystarczyć:
delete from devices
using (
select ctid as cid,
row_number() over (partition by devicename, objectid order by timestamp asc) as rn
from devices
) newest
where newest.cid = devices.ctid
and newest.rn <> 1;
Tworzy tabelę pochodną, która przypisze unikalne numery do każdej kombinacji (adres, nazwa urządzenia, identyfikator obiektu) podając najwcześniejszą (tę z najmniejszym timestamp
wartość) liczba 1. Następnie ten wynik jest używany do usunięcia wszystkich tych, które nie mają liczby 1. Wirtualna kolumna ctid
służy do jednoznacznej identyfikacji tych wierszy (jest to wewnętrzny identyfikator dostarczany przez Postgres).
Zauważ, że w przypadku usunięcia naprawdę dużej liczby wierszy podejście Erwina z pewnością będzie szybsze.
Demo SQLFiddle:http://www.sqlfiddle.com/#!1/5d9fe/ 2