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.
Cosa imparerai
- Comprendere il problema analitico e il contesto decisionale
- Applicare esempi, metriche e controlli a casi reali
Collegamenti
Sessionization e behavioral grouping
Un utente apre l’app alle 8:02, torna alle 8:37, clicca tre prodotti e poi scompare fino al pomeriggio. Nel log sono solo eventi ordinati, ma per il prodotto quei blocchi diventano sessioni, intenzioni e segnali di frizione. Sessionization e behavioral grouping insegna a costruire quel livello intermedio senza inventare storie che i dati non sostengono.
Una scena da cui partire
Leggi la lezione come se dovessi trasformare eventi grezzi in unità analitiche stabili. La scelta del timeout, del criterio di riapertura e del gruppo comportamentale cambia conversioni, retention e diagnosi di UX: per questo va resa esplicita.
- Contesto: Quale comportamento reale vuoi racchiudere in una sessione?
- Metodo: Quale soglia temporale useresti e come la testeresti?
- Applicazione: Quale insight di prodotto emerge solo dopo la sessionizzazione?
Cosa definisce una sessione
Una sessione è un raggruppamento di eventi consecutivi dello stesso utente, separati da altre attività da un periodo di inattività superiore a una soglia. La soglia è arbitraria ma deve essere coerente: Google Analytics usa 30 minuti, Mixpanel usa 30 minuti, Amplitude usa 5 minuti per app mobile e 30 per web. Non c’è una risposta giusta: c’è una risposta utile per il tuo business.
Il pattern SQL per la sessionizzazione è già stato introdotto nella lezione su LAG/LEAD. Qui lo approfondiamo e lo estendiamo al behavioral grouping: raggruppare eventi non solo per prossimità temporale, ma per pattern di comportamento.
Il pattern completo di sessionizzazione
Riprendiamo e rifiniamo il pattern a due passaggi:
Passaggio 1: Marcare l’inizio di ogni nuova sessione
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 -- primo evento, nuova sessione
WHEN EXTRACT(EPOCH FROM (event_time - LAG(event_time)
OVER (PARTITION BY user_id ORDER BY event_time))) > 1800
THEN 1 -- gap > 30 minuti, nuova sessione
ELSE 0
END AS is_new_session
FROM raw_events
)
Passaggio 2: Assegnare un session_id cumulativo
events_with_session AS (
SELECT *,
SUM(is_new_session) OVER (
PARTITION BY user_id
ORDER BY event_time
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) 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: parte da 1 per ogni utente e incrementa a ogni nuova sessione.
Oltre il tempo: behavioral grouping
La sessionizzazione per gap temporale è il caso base. Ma spesso serve raggruppare eventi per cambi di stato o pattern sequenziali.
Pattern: raggruppamento per cambi di stato
Immagina una tabella di sensori IoT che registrano temperature ogni minuto. Vuoi raggruppare le letture in “episodi di surriscaldamento”: sequenze consecutive in cui la temperatura supera 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
Questo pattern è identico alla sessionizzazione, ma il trigger non è un gap temporale: è un cambio di stato logico. È lo stesso algoritmo mentale applicato a un dominio diverso.
Caso reale: Tesla e l’analisi delle sessioni di guida
Tesla raccoglie dati da oltre 4 milioni di veicoli connessi, generando centinaia di miliardi di eventi telemetrici. Uno dei problemi centrali per il team di Autopilot è la sessionizzazione: raggruppare gli eventi di guida in “viaggi” distinti.
La definizione di viaggio di Tesla non è banale. Un guidatore può fermarsi a un semaforo per 2 minuti — è ancora lo stesso viaggio. Può fermarsi in un’area di servizio per 15 minuti — inizia un nuovo viaggio? Dipende: se spegne il motore, sì; se resta in Drive, no. Tesla usa una combinazione di segnali: stato del motore (Drive/Park), velocità (>0 o =0), e posizione GPS (cambi significativi quando il motore è spento).
La query concettuale per raggruppare gli eventi in viaggi:
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 -- motore spento + spostamento significativo
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;
Un paper interno di Tesla del 2022 (citato nel loro 10-K filing) descrive come questo approccio abbia permesso di passare da “sessioni di guida” definite lato veicolo (che consumavano banda e CPU) a sessioni calcolate lato server in batch, riducendo il costo computazionale dell’87%.
Laboratorio pratico a tre livelli
Dataset: clickstream con 50.000 eventi di 500 utenti su un sito e-commerce.
Livello 1 — Sessionizzazione base: Scrivi la query di sessionizzazione con soglia di 30 minuti.
Livello 2 — Sessioni con vincolo di azione: Una sessione termina anche se l’utente raggiunge la pagina thank_you (acquisto completato), indipendentemente dal gap temporale. Aggiungi questa condizione.
Suggerimento: Aggiungi un controllo su event_type nel CASE di is_new_session: se l’evento precedente era purchase, anche l’evento successivo (anche se entro 30 min) inizia una nuova sessione.
Livello 3 — Attribuzione della sessione al canale: Ogni sessione deve essere attribuita al canale del primo evento della sessione (es. organic_search, paid_ad, direct). Estrai il canale del primo evento di ogni sessione usando FIRST_VALUE.
🖥️ Prova in Sandbox
Sessionizzazione base: per ogni evento, calcola il gap temporale rispetto all'evento precedente dello stesso utente (in secondi). Marca come nuova sessione ogni evento che ha un gap > 1800 secondi (30 minuti) o che è il primo evento.
Calcola le statistiche per sessione: per ogni utente, raggruppa gli eventi in sessioni (usa SUM cumulativo) e conta eventi per sessione, durata, e tipo di eventi.
Checkpoint operativi
-
Cosa definisce una sessione? Perché la soglia temporale è una scelta di business e non tecnica?
-
Scrivi il pattern SQL a due passaggi per la sessionizzazione.
-
Come estenderesti la sessionizzazione per raggruppare per cambi di stato (es. surriscaldamento) oltre che per gap temporale?
Riferimenti accademici:
- Kaushik, A. (2010). Web Analytics 2.0. Sybex. Capitolo 7: “Web Data Quality: The Dirty Little Secret.”
- Google Analytics Help. (2024). “How a web session is defined in Universal Analytics vs. Google Analytics 4.”
- Suthar, J. & Patel, P. (2023). “Clickstream Session Identification: A Comparative Study.” Journal of Web Engineering, 22(4).
Controllo di qualità
Prima di usare sessionization e behavioral grouping in una decisione, controlla sempre completezza, duplicati, timezone, definizioni cambiate e segmenti esclusi. Molte analisi apparentemente sofisticate falliscono perché il dato di partenza misura un comportamento diverso da quello che il team crede di osservare.
Problema reale
Nel dominio di advanced SQL, Sessionization e behavioral grouping serve a risolvere questo problema: scrivere query analitiche corrette anche quando grain, finestre, coorti e casi limite diventano complessi. La lezione non va trattata come teoria isolata, ma come un modo per migliorare una scelta concreta con dati, assunzioni esplicite e controlli minimi.
Obiettivo operativo: Comprendere il problema analitico e il contesto decisionale; Applicare esempi, metriche e controlli a casi reali. Se alla fine non sai indicare quale decisione cambia, quale dato osservi e quale errore vuoi evitare, la lezione non è ancora diventata competenza applicata.
Modello concettuale
| Fase | Cosa chiarire | Output |
|---|---|---|
| Domanda | Quale scelta reale deve migliorare? | Decisione da prendere |
| Misura | Quale segnale osservabile rappresenta il problema? | Metrica o dato sorgente |
| Controllo | Quale baseline rende il risultato interpretabile? | Confronto credibile |
| Azione | Che cosa cambia dopo l’analisi? | Prossimo passo operativo |
Il modello concettuale è intenzionalmente semplice: decisione, dato, controllo, azione. Ogni approfondimento tecnico deve rafforzare almeno uno di questi quattro punti.
Formalizzazione rigorosa
Per rendere Sessionization e behavioral grouping analizzabile, definisci prima l’unità di lavoro: riga, partizione, finestra, join, coorte o metrica temporale. Poi collega questa unità a una metrica osservabile: correttezza, performance, duplicati, grain e stabilità del risultato. Infine dichiara la decisione attesa: query, modello intermedio, test SQL o pattern riusabile.
| Elemento | Specifica richiesta |
|---|---|
| Unità di analisi | riga, partizione, finestra, join, coorte o metrica temporale |
| Segnale principale | correttezza, performance, duplicati, grain e stabilità del risultato |
| Baseline | Periodo precedente, gruppo comparabile, benchmark o scenario controfattuale |
| Decisione | query, modello intermedio, test SQL o pattern riusabile |
| Rischio | Scambiare un numero disponibile per una prova sufficiente |
La formalizzazione e solida quando un altro analista può riprodurre la logica, criticare le assunzioni e ottenere la stessa decisione partendo dagli stessi dati.
Esempio o caso studio
Gli eventi utente arrivano come righe isolate, ma la decisione richiede sessioni, sequenze e comportamenti raggruppati. Il lavoro SQL consiste nel definire soglia di inattività, ordinamento, identità e confini della sessione prima di interpretare conversione o engagement.
| Evidenza osservata | Lettura prudente | Azione consigliata |
|---|---|---|
| Il numero migliora | Potrebbe essere effetto reale o variazione normale | Cercare confronto e segmento |
| Un segmento cambia più degli altri | La media aggregata nasconde una differenza | Separare coorti o casi d’uso |
| Il costo cresce insieme al risultato | L’impatto va letto sul margine | Stimare trade-off e sostenibilità |
Lab / esercizio
Livello base
Scrivi una scheda di una pagina per Sessionization e behavioral grouping: decisione da supportare, metrica primaria, baseline, rischio principale e azione se il segnale e confermato.
Livello intermedio
Costruisci una tabella con tre segmenti, periodi o scenari. Per ciascuno indica cosa cambia, quale spiegazione alternativa e plausibile e quale controllo useresti prima di raccomandare un azione.
Livello research-grade
Prepara un decision memo: ipotesi, dati richiesti, criteri di esclusione, controlli di qualità, soglia decisionale, rischio residuo e piano di monitoraggio dopo la decisione.
Dataset e materiali consigliati
Usa warehouse SQL, dati ordini, eventi, sessioni, coorti, revenue e tabelle calendario. Se non hai accesso a dati reali, crea un dataset sintetico con almeno 200 righe, una dimensione temporale, una dimensione segmento e una metrica di outcome.
Errore tipico da evitare
L’errore più comune e usare Sessionization e behavioral grouping come etichetta invece che come processo. Succede quando il team mostra un grafico senza decisione, una metrica senza baseline, o una conclusione senza indicare quale assunzione potrebbe invalidarla.
La domanda di controllo è: se questo risultato fosse instabile, quale scelta sbaglierei? Se la risposta non è concreta, manca ancora il collegamento tra analisi e azione.
Quiz o checkpoint
- Quale decisione concreta dovrebbe migliorare questa lezione?
- Quale unità di analisi rende il problema misurabile?
- Quale baseline useresti per evitare una lettura ingenua?
- Quale errore tipico potrebbe cambiare la conclusione?
- Quale output consegneresti a uno stakeholder non tecnico?
Riepilogo operativo
Sessionization e behavioral grouping diventa utile quando produce una decisione più chiara, non quando aggiunge terminologia. Usa il framework problema, modello, formalizzazione, esempio, lab e checkpoint per trasformare la lezione in pratica verificabile. Categoria: Decisione. Difficoltà: advanced. Tempo stimato: 18 min.
Percorso collegato
Lezioni da leggere insieme
Questi collegamenti portano la lezione dentro il resto del corso: basi da riprendere, passaggi successivi e connessioni tematiche tra moduli.