BigQuery среднее время с ограничением разрыва - PullRequest
0 голосов
/ 30 августа 2018

У меня есть таблица BigQuery, представляющая сообщения, каждое сообщение относится к беседе и имеет дату:

conversation    date    
1               2018-06-22 23:16:46.456 UTC
2               2018-06-05 00:07:12.178 UTC
1               2018-06-22 23:16:46.456 UTC
4               2018-06-05 00:07:12.178 UTC
3               2018-06-22 23:51:28.540 UTC
3               2018-06-23 00:02:59.285 UTC
4               2018-06-04 23:21:59.500 UTC

Мне нужно получить среднее время, проведенное в разговоре

Я использовал этот запрос, чтобы получить его:

SELECT conversation, timestamp_diff(MAX(date), MIN(date), MINUTE) minutes
FROM `Message`
GROUP BY conversation

Но так как некоторые разговоры занимают несколько дней, их нужно разрезать на более мелкие куски, когда разрыв между сообщениями превышает 1 час. Пример:

conversation    date    
2               2018-06-22 00:01:46.456 UTC   # group 1
2               2018-06-22 00:07:12.178 UTC   # group 1
2               2018-06-22 00:16:46.456 UTC   # group 1
2               2018-06-22 01:07:42.178 UTC   # group 1
      there is a gap here
2               2018-06-22 12:51:28.540 UTC   # group 2
2               2018-06-22 13:00:40.486 UTC   # group 2
      there is another gap here
2               2018-06-22 19:54:30.031 UTC   # group 3

Я думаю, что это возможно с помощью аналитических функций: https://cloud.google.com/bigquery/docs/reference/standard-sql/analytic-function-concepts

Но я не понял, как это сделать, любая помощь будет действительно ценной.

1 Ответ

0 голосов
/ 30 августа 2018

ниже для BigQuery Standard SQL

их нужно разрезать на более мелкие куски, если разрыв между сообщениями превышает 1 час:

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 2 conversation, TIMESTAMP '2018-06-22 00:01:46.456 UTC' dt UNION ALL   # group 1
  SELECT 2, '2018-06-22 00:07:12.178 UTC' UNION ALL   # group 1
  SELECT 2, '2018-06-22 00:16:46.456 UTC' UNION ALL   # group 1
  SELECT 2, '2018-06-22 01:07:42.178 UTC' UNION ALL   # group 1
  SELECT 2, '2018-06-22 12:51:28.540 UTC' UNION ALL   # group 2
  SELECT 2, '2018-06-22 13:00:40.486 UTC' UNION ALL   # group 2
  SELECT 2, '2018-06-22 19:54:30.031 UTC'             # group 3
), conversation_groups AS (
  SELECT 
    conversation, dt, 
    SUM(flag) OVER(PARTITION BY conversation ORDER BY dt) conversation_group
  FROM (
    SELECT 
      conversation, dt, 
      SIGN(IFNULL(TIMESTAMP_DIFF(dt, LAG(dt) OVER(PARTITION BY conversation ORDER BY dt), HOUR), 0)) flag
    FROM `project.dataset.table`
  )
)
SELECT *
FROM conversation_groups
ORDER BY conversation, dt   

с результатом как

Row conversation    dt                              conversation_group   
1   2               2018-06-22 00:01:46.456 UTC     0    
2   2               2018-06-22 00:07:12.178 UTC     0    
3   2               2018-06-22 00:16:46.456 UTC     0    
4   2               2018-06-22 01:07:42.178 UTC     0    
5   2               2018-06-22 12:51:28.540 UTC     1    
6   2               2018-06-22 13:00:40.486 UTC     1    
7   2               2018-06-22 19:54:30.031 UTC     2      

Мне нужно получить среднее время, проведенное в разговоре

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 2 conversation, TIMESTAMP '2018-06-22 00:01:46.456 UTC' dt UNION ALL   # group 1
  SELECT 2, '2018-06-22 00:07:12.178 UTC' UNION ALL   # group 1
  SELECT 2, '2018-06-22 00:16:46.456 UTC' UNION ALL   # group 1
  SELECT 2, '2018-06-22 01:07:42.178 UTC' UNION ALL   # group 1
  SELECT 2, '2018-06-22 12:51:28.540 UTC' UNION ALL   # group 2
  SELECT 2, '2018-06-22 13:00:40.486 UTC' UNION ALL   # group 2
  SELECT 2, '2018-06-22 19:54:30.031 UTC'             # group 3
), conversation_groups AS (
  SELECT 
    conversation, dt, 
    SUM(flag) OVER(PARTITION BY conversation ORDER BY dt) conversation_group
  FROM (
    SELECT 
      conversation, dt, 
      SIGN(IFNULL(TIMESTAMP_DIFF(dt, LAG(dt) OVER(PARTITION BY conversation ORDER BY dt), HOUR), 0)) flag
    FROM `project.dataset.table`
  )
)
SELECT conversation, AVG(IF(duration = 0, NULL, duration)) avg_duration
FROM (
  SELECT
    conversation, conversation_group,
    TIMESTAMP_DIFF(MAX(dt), MIN(dt), MINUTE) duration
  FROM conversation_groups
  GROUP BY conversation, conversation_group
)
GROUP BY conversation
ORDER BY conversation

с результатом как

Row conversation    avg_duration     
1   2               37.0     

Примечание: вы можете настроить логику вычисления avg на основе ваших конкретных потребностей / видения того, как это сделать, - но, как это делается выше, - сначала рассчитывается продолжительность каждой группы, а затем усредняется продолжительность в этих группах. принято - и обратите внимание: если продолжительность равна нулю, она заменяется на NULL, поэтому это не влияет на вычисление среднего значения. Длительность рассчитывается в МИНУТАХ, но вы можете использовать ВТОРЫЕ или все, что вам нужно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...