Postgres admite funciones de ventana que se adaptan a esta situación:
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
Para cada combinación de date , symbol , esta consulta devuelve el value y created_time de la fila con el valor más alto (es decir, último ) created_time de esa date y symbol .
Sugeriría este índice:
CREATE UNIQUE INDEX test_table_idx
ON test_table (date, symbol, created_time, value)
Es una cobertura index (tiene todos los valores que necesita para la consulta, obviando la necesidad de acceder a la tabla real, y que ya tenía), pero tenga en cuenta que created_time viene antes value , por lo que los datos ya están en su orden de partición y value es el atributo menos importante, porque no participa en ninguna determinación de qué fila devolver.