Вычислить продолжительность между двумя датами с разными строками в большом запросе (разделе) - PullRequest
0 голосов
/ 10 октября 2019

у меня есть такие данные:

`id      box_id         event               time                     
1       1001           'start'       2019-06-13 16:00                                       
2       1001           'end'         2019-06-13 15:22             
2       2001           'start'       2019-06-18 15:20                
3       1001           'start'       2019-06-13 15:20               
4       2003           'start'       2019-06-18 15:20`

ожидаемые результаты:

date          box_id         start                end              idle 
 2019-06-13    1001       2019-06-13 16:00         NA              0 
 2019-06-13    1001       2019-06-13 15:20    2019-06-13 15:22     2 
 2019-06-18    2001       2019-06-18 15:20         NA              0 
 2019-06-18    2003       2019-06-18 15:20         NA              0

я хочу получить разницу между 2 датами (основанными почти на времени), когда box_id не имеетпочти время с event : end, box_id показывают idle = 0. что я должен делать ? Я прочитал некоторые ссылки, чтобы сделать использование над разделом

Ответы [ 4 ]

1 голос
/ 10 октября 2019

Использование lead():

select cast(time as date) as date,
       box_id,
       time as start_time,
       end_time
from (select t.*,
             lead(time) over (partition by box_id order by time) as end_time
      from t
     ) t
where event = 'start';
0 голосов
/ 11 октября 2019

Немного другое решение (используя LAG):

select
   date(end_time) as date,
   box_id,
   start_time,
   end_time,
   if(pevent = 'start' and event = 'end', timestamp_diff(end_time, start_time,minute), null) as idle
from (
   select 
      box_id, 
      lag(time) over(partition by box_id order by time) as start_time, 
      time as end_time,  
      lag(event) over(partition by box_id order by time) as pevent,
      event
   from `dataset.table`
)
0 голосов
/ 10 октября 2019

Ниже для 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    
0 голосов
/ 10 октября 2019

Hi @Nadyav: ниже приведен набросок псевдокода, с которого можно начать. pseudo code

...