influxdbinfluxql

How to obtain time interval value reports from InfluxDB


Using InfluxDB: Is there any way to build a time-bucketed report of a field value representing a state that persists over time? Ideally in InfluxQL query language

More specifically as an example: Say a measurement contains points that report changes in the light bulb state (On / Off). They could be 0s and 1s as in the example below, or any other value. For example:

time                   light
----                   -----
2022-03-18T00:00:00Z   1
2022-03-18T01:05:00Z   0
2022-03-18T01:55:00Z   0
2022-03-18T02:30:00Z   1
2022-03-18T04:06:00Z   0

The result should be a listing of intervals indicating if this light was on or off during each time interval (e.g. hours), or what percentage of that time it was on. For the given example, the result if grouping hourly should be:

Hour Value
2022-03-18 00:00 1.00
2022-03-18 01:00 0.17
2022-03-18 02:00 0.50
2022-03-18 03:00 1.00
2022-03-18 04:00 0.10

Note that:

Is there a way to implement it in pure InfluxQL, without retrieving potentially big data sets (points) and iterating through them in a client?


Solution

  • I consider that raw data could be obtained by query:

    SELECT "light" FROM "test3" WHERE $timeFilter
    

    Where "test3" is your measurement name and $timeFilter is from... to... time period. In this case we need to use a subquery which will fill our data, let's consider grouping (resolution) time as 1s:

    SELECT last("light") as "filled_light" FROM "test3" WHERE $timeFilter GROUP BY time(1s) fill(previous)
    

    This query gives us 1/0 value every 1s. We will use it as a subquery.

    NOTE: You should be informed that this way does not consider if beginning of data period within $timeFilter has been started with light on or off. This way will not provide any data before hour with any value within $timeFilter.

    In next step you should use integral() function on data you got from subquery, like this:

    SELECT integral("filled_light",1h) from (SELECT last("light") as "filled_light" FROM "test3" WHERE $timeFilter GROUP BY time(1s) fill(previous)) group by time(1h)
    

    This is how it looks on charts:

    This is an example created in Grafana connected to InfluxDB - charts

    And how Result data looks in a table: This is an example created in Grafana connected to InfluxDB - table

    This is not a perfect way of getting it to work but I hope it resolves your problem.