Dans toutes les manières exposées de faire jusqu'à présent, il faut passer par le scan deux fois, une pour la première rangée et une pour la dernière rangée.
En utilisant la fonction de fenêtre "ROW_NUMBER() OVER (...)" et "WITH Queries", vous pouvez effectuer un seul balayage et obtenir les deux éléments.
Fonction de la fenêtre : https://www.postgresql.org/docs/9.6/static/functions-window.html
WITH Queries : https://www.postgresql.org/docs/9.6/static/queries-with.html
Exemple :
WITH scan_plan AS (
SELECT
<some columns>,
ROW_NUMBER() OVER (ORDER BY date DESC) AS first_row, /*It's logical required to be the same as major query*/
ROW_NUMBER() OVER (ORDER BY date ASC) AS last_row /*It's rigth, needs to be the inverse*/
FROM mytable
<maybe some joins here>
WHERE <various conditions>
ORDER BY date DESC)
SELECT
<some columns>
FROM scan_plan
WHERE scan_plan.first_row = 1 OR scan_plan.last_row = 1;
De cette manière, vous n'effectuerez les relations, les filtrages et les manipulations de données qu'une seule fois.
Essayez d'EXPLAIN ANALYZE dans les deux sens.