Для маркетингового анализа мне нужно предоставить данные о первой и последней точке взаимодействия, а также об общем количестве взаимодействий с нашим веб-сайтом.
Упрощенная версия нашей interaction
таблицы выглядит так :
create table interaction (
id varchar(36) primary key,
session_id varchar(36) not null,
timestamp timestamp(3) not null,
utm_source varchar(255) null,
utm_medium varchar(255) null
)
Наш текущий подход выглядит следующим образом:
with interaction_ordered as (
select *,
row_number() over (partition by session_id order by timestamp asc) as row_num_asc,
row_number() over (partition by session_id order by timestamp desc) as row_num_desc
from interaction
)
select first_interaction.session_id as session_id,
first_interaction.timestamp as session_start,
timestampdiff(SECOND, first_interaction.timestamp, last_interaction.timestamp) as session_duration,
count(*) as interaction_count,
first_interaction.utm_source as first_touchpoint,
last_interaction.utm_source as last_touchpoint,
last_interaction.utm_medium as last_medium
from interaction_ordered as interaction
join interaction_ordered as first_interaction using (session_id)
join interaction_ordered as last_interaction using (session_id)
where first_interaction.row_num_asc = 1 and last_interaction.row_num_desc = 1
group by session_id
having session_start between ? - interval 1 day and ? + interval 1 day
В настоящее время мы наблюдаем, что время выполнения масштабируется примерно линейно с нашими данными, что вскоре станет невозможным для вычислений.
Альтернативная идея:
select session_id,
min(timestamp) as session_start,
timestampdiff(
SECOND,
min(timestamp),
max(timestamp)
) as session_duration,
count(*) as interaction_count,
first_value(utm_source) over (partition by session_id order by timestamp) as first_touchpoint,
first_value(utm_source) over (partition by session_id order by timestamp desc) as last_touchpoint,
first_value(utm_medium) over (partition by session_id order by timestamp desc) as last_medium
from interaction
group by session_id
having session_start between ? - interval 1 day and ? + interval 1 day
, но в наших экспериментах мы никогда не видели, чтобы второй запрос был завершен. Следовательно, мы не на 100% уверены, что он дает такие же результаты.
Мы пробовали индексы на timestamp
и (session_id, timestamp)
, но, согласно EXPLAIN
, это не изменило план запроса *. 1020 *
Есть ли какой-нибудь быстрый способ получить отдельные свойства из первой и последней записи на идентификатор сеанса плюс счетчик на идентификатор сеанса? Обратите внимание, что в нашем реальном примере нас интересуют другие параметры, такие как utm_source
и utm_medium
.
EDIT
Примеры данных:
insert into interaction values
('a', 'session_1', '2020-06-15T12:00:00.000', 'search.com', 'search'),
('b', 'session_1', '2020-06-15T12:01:00.000', null, null),
('c', 'session_1', '2020-06-15T12:01:30.000', 'social.com', 'social'),
('d', 'session_1', '2020-06-15T12:02:00.250', 'ads.com', 'ads'),
('e', 'session_2', '2020-06-15T14:00:00.000', null, null),
('f', 'session_2', '2020-06-15T14:12:00.000', null, null),
('g', 'session_2', '2020-06-15T14:25:00.000', 'social.com', 'social'),
('h', 'session_3', '2020-06-16T12:05:00.000', 'ads.com', 'ads'),
('i', 'session_3', '2020-06-16T12:05:01.000', null, null),
('j', 'session_4', '2020-06-15T12:00:00.000', null, null),
('k', 'session_5', '2020-06-15T12:00:00.000', 'search.com', 'search');
Ожидаемый результат:
session_id, session_start, session_duration, interaction_count, first_touchpoint, last_touchpoint, last_medium
session_1, 2020-06-15T12:00:00.000, 120, 4, search.com, ads.com, ads
session_2, 2020-06-15T14:00:00.000, 1500, 3, null, social.com, social
session_3, 2020-06-16T12:05:00.000, 1, 2, ads.com, null, null
session_4, 2020-06-15T12:00:00.000, 0, 1, null, null, null
session_5, 2020-06-15T12:00:00.000, 0, 1, search.com, search.com, search
Я заметил, что мой второй запрос не дает ожидаемого результата. Вместо last_touchpoint
и last_medium
заполняется первое значение. Я пробовал
first_value(utm_source) over (partition by session_id order by timestamp desc) as last_touchpoint,
и last_value(utm_source) over (partition by session_id order by timestamp range between unbounded preceding and unbounded following) as last_touchpoint,