If you want a single query, I suggest a data-modifying CTE like:
WITH cte(bound) AS (SELECT now() AT TIME ZONE 'UTC' - interval '1 day')
, upd AS (
SET next_update = now() AT TIME ZONE 'UTC'
WHERE next_update < cte.bound -- why cast to timestamp?
SELECT *, next_update - cte.bound AS time_to_update
FROM MyTable, cte
WHERE next_update >= cte.bound;
The point being that
SELECT see the same snapshot and
SELECT won't return the newly updated rows. (The fist CTE named
cte is just for convenience, so we don't have to repeat the calculation of the bound.)
time_to_update is an
interval of the form
23:53:27.141289 - hours:minutes:seconds:µs. Negative if there can be future timestamps - and possibly with leading days then:
'-26 days -23:58:35.25222'. Else it cannot be greater than 24h in this query.
next_update is type
timestamp, though the casts in your
UPDATE are inconclusive (contradictory).
now() AT TIME ZONE 'UTC' produces a
timestamp, makes sense if
next_update is of that type. But then why
next_update::timestamp? (And why update a column named "next_update" to
now()? Does not seem to make sense.)