Ok, I managed to do what I wanted with this query:
tableGPSAccuracy = from(bucket: "home_assistant")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "device_tracker.mate10")
|> filter(fn: (r) => r["_field"] == "gps_accuracy")
|> drop(columns: ["_start", "_stop", "domain", "_measurement", "entity_id", "source", "_field"])
tableLatitude = from(bucket: "home_assistant")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "device_tracker.mate10")
|> filter(fn: (r) => r["_field"] == "latitude")
|> drop(columns: ["_start", "_stop", "domain", "_measurement", "entity_id", "source", "_field"])
tableLongitude = from(bucket: "home_assistant")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "device_tracker.mate10")
|> filter(fn: (r) => r["_field"] == "longitude")
|> drop(columns: ["_start", "_stop", "domain", "_measurement", "entity_id", "source", "_field"])
tableVelocity = from(bucket: "home_assistant")
|> range(start: v.timeRangeStart, stop: v.timeRangeStop)
|> filter(fn: (r) => r["_measurement"] == "device_tracker.mate10")
|> filter(fn: (r) => r["_field"] == "velocity")
|> drop(columns: ["_start", "_stop", "domain", "_measurement", "entity_id", "source", "_field"])
tableTmp1 = join(tables: {tLat: tableLatitude, tLon: tableLongitude}, on: ["_time"], method: "inner")
tableTmp2 = join(tables: {tAcc: tableGPSAccuracy, tVel: tableVelocity}, on: ["_time"], method: "inner")
ResultTable = join(tables: {tTmp1: tableTmp1, tTmp2: tableTmp2}, on: ["_time"], method: "inner")
|> duplicate(column: "_value_tLat", as: "lat")
|> duplicate(column: "_value_tLon", as: "lon")
|> drop(columns: ["_value_tLat", "_value_tLon"])
ResultTable |> yield()
This does exactly what I wanted. Now I would just like someone more experienced to confirm that this is the way to do it. To me it looks a bit convoluted…