Postgres supporta funzioni finestra che si adattano a questa situazione:
select date, symbol, value, created_time
from (select *,
rank() over (partition by date, symbol order by created_time desc) as rownum
from test_table) x
where rownum = 1
Per ogni combinazione di date , symbol , questa query restituisce il value e created_time dalla riga con il valore più alto (cioè ultimo ) created_time di quella date e symbol .
Suggerirei questo indice:
CREATE UNIQUE INDEX test_table_idx
ON test_table (date, symbol, created_time, value)
È una copertura index (ha tutti i valori necessari per la query, ovviando alla necessità di accedere alla tabella effettiva e che avevi già), ma tieni presente che created_time viene prima value , quindi i dati sono già nell'ordine di partizione e value è l'attributo meno importante, perché non partecipa ad alcuna determinazione di quale riga restituire.