locf()

The locf (last observation carried forward) function allows you to carry the last seen value in an aggregation group forward. It can only be used in an aggregation query with time_bucket_gapfill. The locf function call cannot be nested inside other function calls.

For more information about gapfilling and interpolation functions, see the hyperfunctions documentation.

Required arguments

NameTypeDescription
valueANY ELEMENTThe value to carry forward

Optional arguments

NameTypeDescription
prevEXPRESSIONThe lookup expression for values before gapfill start
treat_null_as_missingBOOLEANIgnore NULL values in locf and only carry non-NULL values forward

Because the locf function relies on having values before each time bucket to carry forward, it might not have enough data to fill in a value for the first bucket if it does not contain a value. For example, the function needs to look before the first time bucket, but the query’s outer time predicate WHERE time > ... restricts the function to only evaluate values within this time range. This means that the prev expression tells the function how to look for values outside of the range specified by the time predicate. The prev expression is only evaluated when no previous value is returned by the outer query. For example, when the first bucket in the queried time range is empty.

Sample usage

Get the average temperature every day for each device over the last seven days, carrying forward the last value for missing readings:

  1. SELECT
  2. time_bucket_gapfill('1 day', time, now() - INTERVAL '1 week', now()) AS day,
  3. device_id,
  4. avg(temperature) AS value,
  5. locf(avg(temperature))
  6. FROM metrics
  7. WHERE time > now () - INTERVAL '1 week'
  8. GROUP BY day, device_id
  9. ORDER BY day;
  10. day | device_id | value | locf
  11. ------------------------+-----------+-------+------
  12. 2019-01-10 01:00:00+01 | 1 | |
  13. 2019-01-11 01:00:00+01 | 1 | 5.0 | 5.0
  14. 2019-01-12 01:00:00+01 | 1 | | 5.0
  15. 2019-01-13 01:00:00+01 | 1 | 7.0 | 7.0
  16. 2019-01-14 01:00:00+01 | 1 | | 7.0
  17. 2019-01-15 01:00:00+01 | 1 | 8.0 | 8.0
  18. 2019-01-16 01:00:00+01 | 1 | 9.0 | 9.0
  19. (7 row)

Get the average temperature every day for each device over the last seven days, carrying forward the last value for missing readings with out-of-bounds lookup:

  1. SELECT
  2. time_bucket_gapfill('1 day', time, now() - INTERVAL '1 week', now()) AS day,
  3. device_id,
  4. avg(temperature) AS value,
  5. locf(
  6. avg(temperature),
  7. (SELECT temperature FROM metrics m2 WHERE m2.time < now() - INTERVAL '2 week' AND m.device_id = m2.device_id ORDER BY time DESC LIMIT 1)
  8. )
  9. FROM metrics m
  10. WHERE time > now () - INTERVAL '1 week'
  11. GROUP BY day, device_id
  12. ORDER BY day;
  13. day | device_id | value | locf
  14. ------------------------+-----------+-------+------
  15. 2019-01-10 01:00:00+01 | 1 | | 1.0
  16. 2019-01-11 01:00:00+01 | 1 | 5.0 | 5.0
  17. 2019-01-12 01:00:00+01 | 1 | | 5.0
  18. 2019-01-13 01:00:00+01 | 1 | 7.0 | 7.0
  19. 2019-01-14 01:00:00+01 | 1 | | 7.0
  20. 2019-01-15 01:00:00+01 | 1 | 8.0 | 8.0
  21. 2019-01-16 01:00:00+01 | 1 | 9.0 | 9.0
  22. (7 row)