Comparing data from different years, months, ... time ranges

Hello @Jens,
Have you tried using the timeShift() function?

I also find this doc pretty useful:

You can also use an offset in the window() function.

I would query for the two tables in separate variables with different time ranges:
One for year 1 and one for year 2. Then I would shift the time column so they have the same timestamp so you can and then join the data. Now you can compare values across timestamps.

Like:

time1 = from(bucket: "systemstats")
  |> range(start: 2021-10-21T15:49:20.000Z, stop: 2021-10-21T15:50:20.000Z)
  |> filter(fn: (r) => r["_measurement"] == "cpu")
  |> filter(fn: (r) => r["_field"] == "usage_user")
  |> filter(fn: (r) => r["cpu"] == "cpu-total")
  
  |> timeShift(duration: 1m, columns: ["_start", "_stop", "_time"])
//   |> drop(columns: ["_start", "_stop"])
  |> yield(name: "time1")

time2 = from(bucket: "systemstats")
  |> range(start:	2021-10-21T15:50:20.000Z, stop: 2021-10-21T15:51:20.000Z)
  |> filter(fn: (r) => r["_measurement"] == "cpu")
  |> filter(fn: (r) => r["_field"] == "usage_user")
  |> filter(fn: (r) => r["cpu"] == "cpu-total")
//   |> drop(columns: ["_start", "_stop"])
  |> yield(name: "time2")


join(tables: {key1: time1, key2: time2}, on: ["_start", "_stop", "_time","_measurement", "_field", "cpu", "host" ], method: "inner")

This means you’ll have to keep track of which value was in the past but the use of intelligent naming can help with that.