234 lines
No EOL
5.8 KiB
Text
234 lines
No EOL
5.8 KiB
Text
WITH base AS (
|
|
SELECT
|
|
person_id,
|
|
timestamp,
|
|
event,
|
|
properties,
|
|
row_number() OVER (
|
|
PARTITION BY person_id
|
|
ORDER BY timestamp, event
|
|
) AS global_order
|
|
FROM events
|
|
WHERE timestamp >= toDateTime('{start_date}')
|
|
AND timestamp < toDateTime('{end_date}')
|
|
AND event NOT IN ('flutter_error', 'platform_error')
|
|
),
|
|
|
|
ordered_events AS (
|
|
SELECT
|
|
*,
|
|
lagInFrame(timestamp) OVER (
|
|
PARTITION BY person_id
|
|
ORDER BY global_order
|
|
) AS prev_ts,
|
|
|
|
lagInFrame(event) OVER (
|
|
PARTITION BY person_id
|
|
ORDER BY global_order
|
|
) AS prev_event
|
|
FROM base
|
|
),
|
|
|
|
session_flags AS (
|
|
SELECT
|
|
*,
|
|
CASE
|
|
WHEN prev_ts IS NULL THEN 1
|
|
WHEN event = 'Application Opened' THEN 1
|
|
WHEN prev_event IN ('Application Backgrounded', 'Application Closed') THEN 1
|
|
WHEN dateDiff('minute', prev_ts, timestamp) > 10 THEN 1
|
|
ELSE 0
|
|
END AS is_new_session
|
|
FROM ordered_events
|
|
),
|
|
|
|
sessionized AS (
|
|
SELECT
|
|
*,
|
|
sum(is_new_session) OVER (
|
|
PARTITION BY person_id
|
|
ORDER BY global_order
|
|
) AS session_number
|
|
FROM session_flags
|
|
),
|
|
|
|
session_duration_calc AS (
|
|
SELECT
|
|
*,
|
|
dateDiff(
|
|
'second',
|
|
MIN(timestamp) OVER (
|
|
PARTITION BY person_id, session_number
|
|
),
|
|
timestamp
|
|
) AS seconds_since_session_start
|
|
FROM sessionized
|
|
),
|
|
|
|
split_sessions AS (
|
|
SELECT
|
|
*,
|
|
floor(seconds_since_session_start / 1800) AS session_sub_id
|
|
FROM session_duration_calc
|
|
),
|
|
|
|
session_events AS (
|
|
SELECT
|
|
*,
|
|
row_number() OVER (
|
|
PARTITION BY person_id, session_number, session_sub_id
|
|
ORDER BY timestamp, event
|
|
) AS session_index
|
|
FROM split_sessions
|
|
),
|
|
|
|
inter_event_calc AS (
|
|
SELECT
|
|
person_id,
|
|
session_number,
|
|
session_sub_id,
|
|
timestamp,
|
|
event,
|
|
properties,
|
|
session_index,
|
|
|
|
lagInFrame(timestamp) OVER (
|
|
PARTITION BY person_id, session_number, session_sub_id
|
|
ORDER BY session_index
|
|
) AS prev_ts_in_session,
|
|
|
|
CASE
|
|
WHEN session_index = 1 THEN NULL
|
|
ELSE greatest(
|
|
0,
|
|
dateDiff(
|
|
'second',
|
|
lagInFrame(timestamp) OVER (
|
|
PARTITION BY person_id, session_number, session_sub_id
|
|
ORDER BY session_index
|
|
),
|
|
timestamp
|
|
)
|
|
)
|
|
END AS inter_event_time_seconds
|
|
FROM session_events
|
|
),
|
|
|
|
session_stats AS (
|
|
SELECT
|
|
person_id,
|
|
session_number,
|
|
session_sub_id,
|
|
|
|
COUNT(*) AS event_count,
|
|
|
|
uniqExact(event) AS unique_event_types,
|
|
|
|
uniqExact(
|
|
if(
|
|
event = '$screen',
|
|
replaceRegexpOne(
|
|
JSONExtractString(properties, '$screen_name'),
|
|
'\\?.*$',
|
|
''
|
|
),
|
|
NULL
|
|
)
|
|
) AS screens_visited,
|
|
|
|
MIN(timestamp) AS session_start,
|
|
MAX(timestamp) AS session_end,
|
|
|
|
dateDiff(
|
|
'second',
|
|
MIN(timestamp),
|
|
MAX(timestamp)
|
|
) AS duration_seconds,
|
|
|
|
COUNT(*) * 60.0 /
|
|
greatest(
|
|
dateDiff(
|
|
'second',
|
|
MIN(timestamp),
|
|
MAX(timestamp)
|
|
),
|
|
1
|
|
) AS events_per_minute,
|
|
|
|
AVG(inter_event_time_seconds) AS inter_event_time_mean_seconds,
|
|
|
|
median(inter_event_time_seconds) AS inter_event_time_median_seconds,
|
|
|
|
max(inter_event_time_seconds) AS max_inter_event_gap_seconds,
|
|
|
|
sqrt(
|
|
varSamp(inter_event_time_seconds)
|
|
) AS inter_event_time_std_seconds,
|
|
|
|
toHour(MIN(timestamp)) AS session_start_hour,
|
|
|
|
toDayOfWeek(MIN(timestamp)) AS session_day_of_week,
|
|
|
|
uniqExact(
|
|
toStartOfHour(timestamp)
|
|
) AS distinct_hours_active
|
|
|
|
FROM inter_event_calc
|
|
GROUP BY
|
|
person_id,
|
|
session_number,
|
|
session_sub_id
|
|
|
|
HAVING
|
|
COUNT(*) > 2
|
|
AND dateDiff(
|
|
'second',
|
|
MIN(timestamp),
|
|
MAX(timestamp)
|
|
) >= 4
|
|
)
|
|
|
|
SELECT
|
|
person_id,
|
|
|
|
concat(
|
|
toString(person_id),
|
|
'_',
|
|
toString(session_number),
|
|
'_',
|
|
toString(session_sub_id)
|
|
) AS session_id,
|
|
|
|
session_start,
|
|
-- 24-Hour Cyclical Encoding for Session Start
|
|
sin(2 * pi() * (toUnixTimestamp(session_start) - toUnixTimestamp(toStartOfDay(session_start))) / 86400) AS session_start_sin,
|
|
cos(2 * pi() * (toUnixTimestamp(session_start) - toUnixTimestamp(toStartOfDay(session_start))) / 86400) AS session_start_cos,
|
|
|
|
session_end,
|
|
-- 24-Hour Cyclical Encoding for Session End
|
|
sin(2 * pi() * (toUnixTimestamp(session_end) - toUnixTimestamp(toStartOfDay(session_end))) / 86400) AS session_end_sin,
|
|
cos(2 * pi() * (toUnixTimestamp(session_end) - toUnixTimestamp(toStartOfDay(session_end))) / 86400) AS session_end_cos,
|
|
|
|
event_count,
|
|
unique_event_types,
|
|
screens_visited,
|
|
|
|
duration_seconds,
|
|
events_per_minute,
|
|
|
|
inter_event_time_mean_seconds,
|
|
inter_event_time_median_seconds,
|
|
inter_event_time_std_seconds,
|
|
max_inter_event_gap_seconds,
|
|
|
|
session_start_hour,
|
|
|
|
session_day_of_week,
|
|
-- 7-Day Cyclical Encoding for Day of the Week
|
|
sin(2 * pi() * session_day_of_week / 7) AS session_day_of_week_sin,
|
|
cos(2 * pi() * session_day_of_week / 7) AS session_day_of_week_cos,
|
|
|
|
distinct_hours_active
|
|
|
|
FROM session_stats
|
|
ORDER BY session_start DESC |