From the documentation:
Analytic functions compute an aggregate value based on a group of rows. They differ from aggregate functions in that they return multiple rows for each group.
...
Analytic functions are the last set of operations performed in a query except for the final ORDER BY clause. All joins and all WHERE, GROUP BY, and HAVING clauses are completed before the analytic functions are processed.
Your inner select is pulling all rows from your table because it has no where
clause; since it has to fetch every row the index isn't helpful and it might as well do a full table scan. Using the index on datestamp
would be worse - it would have to do a full scan of the index and then access every data row anyway, increasing the IO. If you run the inner select on its own you'll see it returns a lot of rows, not just one.
The outer select then matches a specific row (or rows) from the inner one. That comparison can't be pushed into the inner select because of when in the processing the analytic value is calculated.