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 da Andrii Dyshkantiuk
Lezione 142 / 216 Livello: Avanzato Durata: 18 min Prerequisiti: 1

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

Prova tu

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.

Ctrl+Enter per eseguire
Prova tu

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.

Ctrl+Enter per eseguire

Checkpoint operativi

  1. Cosa definisce una sessione? Perché la soglia temporale è una scelta di business e non tecnica?

  2. Scrivi il pattern SQL a due passaggi per la sessionizzazione.

  3. 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

FaseCosa chiarireOutput
DomandaQuale scelta reale deve 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

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.

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 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 osservataLettura prudenteAzione consigliata
Il numero miglioraPotrebbe essere effetto reale o variazione normaleCercare confronto e segmento
Un segmento cambia più degli altriLa media aggregata nasconde una differenzaSeparare coorti o casi d’uso
Il costo cresce insieme al risultatoL’impatto va letto sul margineStimare 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

  1. Quale decisione concreta dovrebbe migliorare questa lezione?
  2. Quale unità di analisi rende il problema misurabile?
  3. Quale baseline useresti per evitare una lettura ingenua?
  4. Quale errore tipico potrebbe cambiare la conclusione?
  5. 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.