It has lot of GROUPS and UNNEST as range of dates increases or interval decreases it take time.
Check is this what you are expecting and how it performs.
SELECT d.panelid, d.sensorid, MILLIS_TO_STR(iv) AS interval, MIN([ABS(STR_TO_MILLIS(el.timestamp)-iv),el])[1] AS el FROM (
SELECT d.panelid, d.sensorid,
ARRAY el FOR el IN d.data WHEN el.timestamp BETWEEN "2015-06-04T09:00:00" AND "2015-07-05T17:00:00" END AS data,
ARRAY v FOR v IN ARRAY_RANGE(STR_TO_MILLIS("2015-06-04T09:00:00"),
STR_TO_MILLIS("2015-07-05T17:00:00"),STR_TO_DURATION("12h")/1000000) END AS interval
FROM `data` d WHERE d.panelid="a-si" AND d.sensorid="voc" AND d.date BETWEEN "2015-06-04" AND "2015-07-05") AS d
UNNEST d.data AS el UNNEST d.interval AS iv
GROUP BY d.panelid,d.sensorid, iv;