Vai al contenuto principale
Esercizi guidati sulle Window Functions - immagine ufficiale della lezione su GinnyTech, creata da AD

Sessionization e behavioral grouping

Sessionization e behavioral grouping. Lezione core del modulo Advanced SQL for Analytical Systems con problema reale, modello concettuale, formalizzazione rigorosa, caso applicato, lab a 3 livelli e checkpoint finale.

AD
Creato daAndrii Dyshkantiuk
Lezione 142 / 236Livello: AvanzatoDurata: 18 minPrerequisiti: 1

Cosa imparerai

  • Comprendere il problema analitico e il contesto decisionale
  • Applicare esempi, metriche e controlli a casi reali

Sessionization e raggruppamento comportamentale

Un utente apre l’app alle 8:02, torna alle 8:37, clicca tre prodotti e poi sparisce fino al pomeriggio. Nel log ci sono solo eventi ordinati nel tempo, ma per chi lavora sul prodotto quei blocchi diventano sessioni, intenzioni e segnali di attrito. La sessionizzazione e il raggruppamento comportamentale servono a costruire questo livello intermedio senza inventare storie che i dati non sostengono.

Il problema da risolvere

Con SQL avanzato il compito è trasformare eventi grezzi in unità di analisi stabili e significative. Decidere cosa è una sessione, quale soglia temporale usare e come raggruppare i comportamenti incide direttamente su metriche come conversioni, retention e diagnosi dell’esperienza utente. La soglia temporale è una scelta di business, non tecnica: deve riflettere il comportamento reale che vuoi catturare.

Come ragionare sul raggruppamento

Uno schema essenziale guida ogni approfondimento tecnico, che deve rafforzare almeno una di queste quattro fasi.

FaseCosa chiarireOutput
DomandaQuale decisione reale vogliamo migliorare?Decisione da prendere
MisuraQuale segnale osservabile rappresenta il problema?Metrica o dato sorgente
ControlloQuale baseline rende il risultato interpretabile?Confronto credibile
AzioneChe cosa cambia dopo l’analisi?Prossimo passo operativo

Rendere l’analisi riproducibile

Perché la sessionizzazione sia analizzabile servono alcune definizioni precise, dall’unità di analisi al rischio da tenere d’occhio.

ElementoSpecifica richiesta
Unità di analisiRiga, partizione, finestra, join, coorte o metrica temporale
Segnale principaleCorrettezza, performance, duplicati, grain e stabilità del risultato
BaselinePeriodo precedente, gruppo comparabile, benchmark o scenario controfattuale
DecisioneQuery, modello intermedio, test SQL o pattern riusabile
RischioScambiare un numero disponibile per una prova sufficiente

La formalizzazione regge quando un altro analista, partendo dagli stessi dati, può riprodurre la logica e arrivare alla stessa decisione.

Il pattern SQL della sessionizzazione

Gli eventi utente arrivano come righe isolate, ma la decisione richiede sessioni e sequenze raggruppate. Sessionizzare significa fissare soglia di inattività, ordinamento, identità e confini della sessione prima di interpretare conversione o engagement.

Il primo passaggio individua dove inizia una nuova sessione. Una nuova sessione comincia quando l’evento è il primo dell’utente oppure quando dal contatto precedente sono passati più di 1800 secondi:

WITH events_with_gap AS (
  SELECT
    user_id,
    event_time,
    event_type,
    LAG(event_time) OVER (PARTITION BY user_id ORDER BY event_time) AS prev_event_time,
    CASE
      WHEN LAG(event_time) OVER (PARTITION BY user_id ORDER BY event_time) IS NULL THEN 1
      WHEN EXTRACT(EPOCH FROM (event_time - LAG(event_time) OVER (PARTITION BY user_id ORDER BY event_time))) > 1800 THEN 1
      ELSE 0
    END AS is_new_session
  FROM raw_events
)

Il secondo passaggio assegna un numero progressivo alla sessione con una somma cumulativa:

events_with_session AS (
  SELECT *,
    SUM(is_new_session) OVER (PARTITION BY user_id ORDER BY event_time ROWS UNBOUNDED PRECEDING) AS session_number
  FROM events_with_gap
)
SELECT
  user_id,
  session_number,
  MIN(event_time) AS session_start,
  MAX(event_time) AS session_end,
  COUNT(*) AS events_in_session,
  EXTRACT(EPOCH FROM (MAX(event_time) - MIN(event_time))) AS session_duration_s
FROM events_with_session
GROUP BY user_id, session_number;

Il session_number è un contatore cumulativo che parte da 1 per ogni utente e cresce a ogni nuova sessione.

Dal gap temporale ai cambi di stato

Oltre al gap temporale capita di dover raggruppare eventi per cambi di stato o pattern sequenziali. In una tabella di sensori IoT che misurano la temperatura ogni minuto, per esempio, può servire raggruppare gli episodi di surriscaldamento, cioè le temperature consecutive sopra i 30°C.

WITH temp_flagged AS (
  SELECT
    sensor_id,
    measured_at,
    temperature,
    CASE WHEN temperature > 30 THEN 0 ELSE 1 END AS state,
    LAG(CASE WHEN temperature > 30 THEN 0 ELSE 1 END) OVER (PARTITION BY sensor_id ORDER BY measured_at) AS prev_state
  FROM sensor_readings
),
state_changes AS (
  SELECT *,
    CASE WHEN state != prev_state OR prev_state IS NULL THEN 1 ELSE 0 END AS is_new_episode
  FROM temp_flagged
)
SELECT
  sensor_id,
  SUM(is_new_episode) OVER (PARTITION BY sensor_id ORDER BY measured_at ROWS UNBOUNDED PRECEDING) AS episode_id,
  MIN(measured_at) AS episode_start,
  MAX(measured_at) AS episode_end,
  MAX(temperature) AS peak_temp
FROM state_changes
WHERE state = 0  -- solo episodi di surriscaldamento
GROUP BY sensor_id, episode_id
HAVING COUNT(*) >= 5;  -- almeno 5 minuti consecutivi

Il pattern è lo stesso della sessionizzazione, solo che il trigger è un cambio di stato logico invece di un gap temporale.

Un caso applicato: Tesla e le sessioni di guida

Tesla raccoglie dati da milioni di veicoli connessi e genera volumi enormi di eventi telemetrici. Per il team Autopilot la sessionizzazione serve a raggruppare gli eventi in viaggi distinti, e la definizione di viaggio non è banale: una sosta di 2 minuti a un semaforo non interrompe il viaggio, mentre una sosta di 15 minuti in area di servizio può interromperlo, a seconda dello stato del motore e della posizione.

WITH vehicle_events AS (
  SELECT
    vin,
    event_time,
    gear,          -- 'P', 'D', 'R', 'N'
    speed,
    lat, lon,
    LAG(gear) OVER (PARTITION BY vin ORDER BY event_time) AS prev_gear,
    LAG(lat) OVER (PARTITION BY vin ORDER BY event_time) AS prev_lat,
    LAG(lon) OVER (PARTITION BY vin ORDER BY event_time) AS prev_lon
  FROM telemetry
),
trip_starts AS (
  SELECT *,
    CASE
      WHEN prev_gear IS NULL THEN 1
      WHEN prev_gear = 'P' AND gear = 'D'
        AND haversine(prev_lat, prev_lon, lat, lon) > 0.1
        THEN 1
      ELSE 0
    END AS is_new_trip
  FROM vehicle_events
)
SELECT vin,
  SUM(is_new_trip) OVER (PARTITION BY vin ORDER BY event_time ROWS UNBOUNDED PRECEDING) AS trip_id,
  COUNT(*) AS events,
  MAX(speed) AS max_speed,
  MAX(event_time) - MIN(event_time) AS duration
FROM trip_starts
GROUP BY vin, trip_id;

Spostando la sessionizzazione lato server in batch, Tesla ha ridotto in modo netto i costi computazionali.

Esercitarsi sui dati

Per allenarsi vanno bene dati di clickstream, ordini, sessioni, coorti e tabelle temporali, e in mancanza di dati reali basta un dataset sintetico con almeno 200 righe. Un primo esercizio consiste nello scrivere la query di sessionizzazione con soglia di 30 minuti su un dataset clickstream. Da lì si estende la logica facendo terminare una sessione anche quando l’utente raggiunge la pagina thank_you. L’esercizio più impegnativo è attribuire ogni sessione al canale del primo evento usando FIRST_VALUE.

L’errore tipico da evitare

L’errore più comune è usare sessionization e behavioral grouping come etichetta senza collegare i risultati a una decisione concreta. Senza baseline e senza dire quale assunzione potrebbe invalidare il risultato, l’analisi rischia di essere inutile o fuorviante.

Per verificare di avere capito, prova a spiegare cosa definisce una sessione e perché la soglia è una scelta di business, qual è il pattern SQL a due passaggi della sessionizzazione, come estenderesti la logica per raggruppare per cambi di stato, quale errore tipico può invalidare una conclusione e quale output consegneresti a uno stakeholder non tecnico.

Riepilogo operativo

Sessionization e behavioral grouping diventano strumenti efficaci solo quando producono decisioni più chiare e azioni concrete. Lo stesso percorso vale sempre: problema, schema di ragionamento, formalizzazione, esempio, esercizio e controllo della comprensione, e così la teoria diventa pratica applicata.


Riferimenti accademici: Kaushik (2010), Google Analytics Help (2024), Suthar & Patel (2023).

Controllo di qualità

Prima di usare la sessionizzazione in decisioni operative, verifica completezza, duplicati, timezone, definizioni cambiate e segmenti esclusi. Molte analisi falliscono perché il dato misura un comportamento diverso da quello che il team crede di osservare.