Ниже для BigQuery Standard SQL
#standardSQL
SELECT MIN(day) AS day, box_id,
MAX(IF(event = 'start', time, NULL)) start,
MAX(IF(event = 'end', time, NULL)) `end`,
IFNULL(TIMESTAMP_DIFF(MAX(IF(event = 'end', time, NULL)), MAX(IF(event = 'start', time, NULL)), SECOND), 0) idle
FROM (
SELECT box_id, event, PARSE_TIMESTAMP('%Y-%m-%d %H:%M', time) time, PARSE_DATE('%Y-%m-%d', SUBSTR(time, 1, 10)) AS day, COUNTIF(event = 'start') OVER(win) grp
FROM `project.dataset.table`
WINDOW win AS (PARTITION BY box_id ORDER BY time)
)
GROUP BY grp, box_id
Если применить к образцу данных из вашего вопроса
WITH `project.dataset.table` AS (
SELECT 1 id, 1001 box_id, 'start' event, '2019-06-13 16:00' time UNION ALL
SELECT 2, 1001, 'end', '2019-06-13 15:22' UNION ALL
SELECT 2, 2001, 'start', '2019-06-18 15:20' UNION ALL
SELECT 3, 1001, 'start', '2019-06-13 15:20' UNION ALL
SELECT 4, 2003, 'start', '2019-06-18 15:20'
)
результат равен
Row day box_id start end idle
1 2019-06-13 1001 2019-06-13 15:20:00 UTC 2019-06-13 15:22:00 UTC 120
2 2019-06-13 1001 2019-06-13 16:00:00 UTC null 0
3 2019-06-18 2001 2019-06-18 15:20:00 UTC null 0
4 2019-06-18 2003 2019-06-18 15:20:00 UTC null 0