How to write an SQL query generating a history of the sums of a column at different timestamps?

Consider below approach

select event_timestamp, sum(ifnull(coalesce(x, prev_x), 0)) x_sum
from (
  select *, 
    first_value(x ignore nulls) over(partition by thing_id order by event_timestamp desc rows between 1 following and unbounded following) prev_x
  from (
    select *
    from (select distinct thing_id from events)
    cross join (select distinct event_timestamp from events)
    left join events using (event_timestamp, thing_id)
  )
)
group by event_timestamp    

if applied to sample data in your question - output is

enter image description here


Having found explanations of the greatest-n-per-group problem, I think I managed to write a solution. It works fine with the given minimal example, but I'm not 100% sure if it works perfectly in general. (And I guess it can be simplified.)

WITH
  events AS (
  SELECT 1 AS thing_id, 1 AS x, TIMESTAMP('2021-12-01 00:00:00') AS event_timestamp
  UNION ALL
  SELECT 1, 3, TIMESTAMP('2021-12-01 00:01:00')
  UNION ALL
  SELECT 2, 5, TIMESTAMP('2021-12-01 00:02:00')
  UNION ALL
  SELECT 1, 2, TIMESTAMP('2021-12-01 00:03:00')
  UNION ALL
  SELECT 1, 0, TIMESTAMP('2021-12-01 00:04:00')
),
  state_timestamps AS (
  SELECT
    event_timestamp state_timestamp
  FROM
    events),
  states AS (
  SELECT
    thing_id,
    state_timestamp,
    event_timestamp,
    x
  FROM
    events
  CROSS JOIN
    state_timestamps
  WHERE
    event_timestamp <= state_timestamp ),
  latest_states AS (
  SELECT
    a.thing_id,
    a.state_timestamp,
    a.event_timestamp,
    a.x
  FROM
    states a
  INNER JOIN (
    SELECT
      thing_id,
      state_timestamp,
      MAX(event_timestamp) event_timestamp
    FROM
      states
    GROUP BY
      thing_id,
      state_timestamp ) b
  ON
    a.thing_id = b.thing_id
    AND a.event_timestamp = b.event_timestamp
    AND a.state_timestamp = b.state_timestamp),
  sum_states AS (
  SELECT
    state_timestamp,
    SUM(x) x_sum
  FROM
    latest_states
  GROUP BY
    state_timestamp
  ORDER BY
    state_timestamp)
SELECT
  *
FROM
  sum_states

Output:

+---------------------+-------+
|   state_timestamp   | x_sum |
+---------------------+-------+
| 2021-12-01 00:00:00 |     1 |
| 2021-12-01 00:01:00 |     3 |
| 2021-12-01 00:02:00 |     8 |
| 2021-12-01 00:03:00 |     7 |
| 2021-12-01 00:04:00 |     5 |
+---------------------+-------+