BigQuery SQL - объединить два столбца, если они в последовательные дни - PullRequest
1 голос
/ 08 апреля 2020

Я ищу способ скорректировать этот sql запрос, выполняемый в BigQuery, чтобы он возвращал общее количество для отправленных типов событий, которые происходят два или даже три дня подряд.

SELECT date(EventDate) as EventDate, EventType, count(*) as count FROM `Database.Table`
    where date(EventDate) > DATE_SUB (CURRENT_DATE, INTERVAL 100 DAY)
    Group by 1,2 
    ORDER by 1,2

Ответ сверху Запрос:

| Row    | EventDate | EventType | count |
| ------ | --------- |-----------|-------|
| 1      | 2019-02-06|  Sent     |    4  |
| 2      | 2019-02-07|  Sent     |    5  |
| 3      | 2019-02-12|  NotSent  |    7  |
| 4      | 2019-02-13|  Bounces  |    22 |
| 5      | 2019-02-14|  Bounces  |    22 |
| 6      | 2019-03-06|  Sent     |    2  |
| 7      | 2019-03-07|  Sent     |    4  |
| 8      | 2019-03-07|  NotSent  |    5  |
| 9      | 2019-03-12|  Bounces  |    7  |
| 10     | 2019-03-13|  Sent     |    22 |
| 11     | 2019-04-05|  Sent     |    2  |

Ответ, который я хотел бы получить:

| Row    | EventDate | EventType | count |
| ------ | --------- |-----------|-------|
| 1      | 2019-02-06|  Sent     |    9  |
| 2      | 2019-02-12|  NotSent  |    7  |
| 3      | 2019-02-13|  Bounces  |    22 |
| 4      | 2019-02-14|  Bounces  |    22 |
| 5      | 2019-03-06|  Sent     |    6  |
| 6      | 2019-03-07|  NotSent  |    5  |
| 7      | 2019-03-12|  Bounces  |    7  |
| 8      | 2019-03-13|  Sent     |    22 |
| 9      | 2019-04-05|  Sent     |    2  |

Что-то в этом духе, поэтому я могу объединить два счета с EventType 'Sent' для последовательного дней и показывать другие типы событий без их объединения, например, Bounces и NotSent.

Ответы [ 2 ]

2 голосов
/ 09 апреля 2020

Я написал запрос, который объединяет все два последовательных дня в таблице.
Он дает тот же результат, что и вы.

Я думаю, вы имели в виду '2019-03-06' в 5-й строке , поэтому я исправил это в своем фиктивном разделе данных.

WITH
data AS (
  SELECT CAST('2019-02-06' as date) as EventDate, 4 as count union all
  SELECT CAST('2019-02-07' as date) as EventDate, 5 as count union all
  SELECT CAST('2019-02-12' as date) as EventDate, 7 as count union all
  SELECT CAST('2019-02-13' as date) as EventDate, 22 as count union all
  SELECT CAST('2019-03-06' as date) as EventDate, 2 as count
),
data_with_steps AS (
  SELECT *, 
    IF(DATE_DIFF(EventDate, LAG(EventDate) OVER (ORDER BY EventDate), day) > 2, 1, 0) as new_step
  FROM data
),
data_grouped AS (
  SELECT *, 
    SUM(new_step) OVER (ORDER BY EventDate) as step_group
  FROM data_with_steps
)
SELECT MIN(EventDate) as EventDate, sum(count) as count
FROM data_grouped
GROUP BY step_group

Итак, как это работает?
Сначала я вычисляю разницу дат с предыдущим днем. Если это более 2 дней, я устанавливаю значение 1, иначе 0 для нового столбца new_step.
Затем я вычисляю совокупную сумму столбца new_step и называю ее step_group.
Выходные данные Первые два шага:
enter image description here

На последнем шаге я группирую таблицу по step_group и получаю минимальную дату в качестве даты события, а также сумму для получения количества групп.
enter image description here

Редактировать: чтобы добавить другие события без группировки, я добавил новую версию. Я думаю, что наиболее интуитивный и простой способ - использовать Union All для этой проблемы. Таким образом, вы можете использовать этот обновленный запрос для включения других событий без группировки.

WITH
data AS (
  SELECT CAST('2019-02-06' as date) as EventDate, 'Sent' as EventType, 4 as count union all
  SELECT CAST('2019-02-07' as date) as EventDate, 'Sent' as EventType, 5 as count union all
  SELECT CAST('2019-02-12' as date) as EventDate, 'Sent' as EventType, 7 as count union all
  SELECT CAST('2019-02-13' as date) as EventDate, 'Sent' as EventType, 22 as count union all
  SELECT CAST('2019-03-06' as date) as EventDate, 'Sent' as EventType, 2 as count union all
  SELECT CAST('2019-02-12' as date) as EventDate, 'NotSent' as EventType, 7 as count union all
  SELECT CAST('2019-03-07' as date) as EventDate, 'NotSent' as EventType, 5 as count union all
  SELECT CAST('2019-02-13' as date) as EventDate, 'Bounces' as EventType, 22 as count union all
  SELECT CAST('2019-02-14' as date) as EventDate, 'Bounces' as EventType, 22 as count union all
  SELECT CAST('2019-03-12' as date) as EventDate, 'Bounces' as EventType, 7 as count
),
data_with_steps AS (
  SELECT *, 
    IF(DATE_DIFF(EventDate, LAG(EventDate) OVER (ORDER BY EventDate), day) > 2, 1, 0) as new_step
  FROM data
  WHERE EventType = 'Sent'
),
data_grouped AS (
  SELECT *, 
    SUM(new_step) OVER (ORDER BY EventDate) as step_group
  FROM data_with_steps
)
SELECT EventType, MIN(EventDate) as EventDate, sum(count) as count
FROM data_grouped
GROUP BY EventType, step_group

UNION ALL

SELECT EventType, EventDate, count
FROM data
WHERE EventType != 'Sent'
0 голосов
/ 08 апреля 2020

Это проблема пробелов и островков. Самый простой способ - использовать row_number() и вычитание для определения «островков». А затем совокупность:

select min(row), eventType, min(eventDate), sum(count)
from (select t.*,
             row_number() over (partition by eventType order by eventDate) as seqnum
      from t
     ) t
group by eventType, dateadd(eventDate, interval -seqnum day)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...