Trasformare i dati con denormalizzazione e pivot

Completato

La ridenozione della struttura dei dati è una parte fondamentale della creazione di soluzioni di analisi efficaci. La denormalizzazione, la pivoting e l'unpivot sono tecniche di trasformazione che consentono di riorganizzare i dati tra formati normalizzati e aggregati, ognuno dei quali serve diverse esigenze di analisi e modellazione.

In questa lezione si apprenderà come appiattire le tabelle normalizzate per query più veloci, ruotare le righe in colonne per l'analisi incrociata e invertire tale processo quando è necessario normalizzare set di dati ampi.

Capire la denormalizzazione

I database normalizzati riducono la ridondanza dei dati suddividendo le informazioni tra più tabelle correlate. Sebbene questa progettazione funzioni bene per i sistemi transazionali, crea sfide per l'analisi. Le query devono unire molte tabelle, rallentando le prestazioni e aumentando la complessità.

La denormalizzazione risolve questi problemi appiattindo le tabelle correlate in tabelle meno ampie. Nelle tabelle dei fatti, i dati vengono combinati direttamente dalle tabelle delle dimensioni, eliminando la necessità di utilizzare i join durante la fase di query.

Diagramma che illustra la denormalizzazione.

Si consideri un database di vendita con tabelle separate per ordini, clienti e prodotti. Una query normalizzata richiede più join:

-- Normalized query with multiple joins
SELECT o.order_id,
       o.order_date,
       c.customer_name,
       c.region,
       p.product_name,
       p.category,
       o.quantity,
       o.total_price
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
JOIN products p ON o.product_id = p.product_id;

Una tabella denormalizzata archivia queste informazioni insieme:

-- Create a denormalized orders table
CREATE OR REPLACE TABLE sales.orders_denormalized AS
SELECT o.order_id,
       o.order_date,
       c.customer_name,
       c.region,
       p.product_name,
       p.category,
       o.quantity,
       o.total_price
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
JOIN products p ON o.product_id = p.product_id;

Le query sulla tabella denormalizzata vengono eseguite più velocemente perché non sono necessari join. Questo approccio è comune quando si creano schemi star e data mart per gli strumenti di business intelligence. Il compromesso è l'aumento dello spazio di archiviazione e la necessità di aggiornare le tabelle denormalizzate quando cambiano i dati di origine.

Suggerimento

Denormalizzare i dati nelle tabelle di livello gold quando le prestazioni delle query sono più importanti rispetto all'efficienza di archiviazione. Le tabelle bronze mantengono i dati di origine non elaborati e le tabelle silver mantengono i dettagli puliti e integrati che rimangono flessibili per la modellazione downstream.

Trasformare le righe in colonne

Il pivot trasforma valori univoci da una colonna in colonne separate, convertendo un formato di tabella "long" in uno "wide". Questa trasformazione è particolarmente utile quando si preparano i dati per report o dashboard incrociati.

Diagramma che illustra la trasformazione di righe in colonne (pivoting).

La clausola PIVOT richiede una funzione di aggregazione perché più righe sorgente potrebbero essere mappate sulla stessa cella nel risultato pivotato. Specifica i valori di colonna che diventano nuovi nomi di colonna usando le clausole FOR e IN.

Prendere in considerazione i dati relativi alle vendite trimestrali archiviati in un formato lungo:

-- Create sample sales data
CREATE OR REPLACE TEMP VIEW quarterly_sales(year, quarter, region, revenue) AS
VALUES (2024, 1, 'East', 150000),
       (2024, 2, 'East', 175000),
       (2024, 3, 'East', 160000),
       (2024, 4, 'East', 200000),
       (2024, 1, 'West', 180000),
       (2024, 2, 'West', 165000),
       (2024, 3, 'West', 190000),
       (2024, 4, 'West', 210000),
       (2025, 1, 'East', 165000),
       (2025, 2, 'East', 185000);

-- View data in long format
SELECT * FROM quarterly_sales;

Questa query restituisce i ricavi come righe separate per ogni trimestre. Per confrontare i trimestri affiancati, ruotare i dati:

-- Pivot quarters into columns
SELECT year, region, Q1, Q2, Q3, Q4
FROM quarterly_sales
PIVOT (
  SUM(revenue)
  FOR quarter IN (1 AS Q1, 2 AS Q2, 3 AS Q3, 4 AS Q4)
);

Il risultato mostra i ricavi trimestrali di ogni area come colonne, rendendo semplici i confronti annuali nell'anno:

year region Primo trimestre Secondo trimestre T3 quarto trimestre
2024 A est 150000 175.000 160.000 200000
2024 Ovest 180000 165000 190000 210000
2025 A est 165000 185000 nullo nullo

È possibile applicare più funzioni di aggregazione in una singola operazione pivot:

-- Pivot with multiple aggregations
SELECT year, Q1_total, Q1_avg, Q2_total, Q2_avg
FROM (SELECT year, quarter, revenue FROM quarterly_sales)
PIVOT (
  SUM(revenue) AS total,
  AVG(revenue) AS avg
  FOR quarter IN (1 AS Q1, 2 AS Q2)
);

In questo modo vengono create colonne sia per la somma che per la media dei ricavi di ogni trimestre.

Annullare ilpivot delle colonne in righe

L'unpivoting esegue la trasformazione inversa: converte nuovamente le colonne in righe. Usare l'unpivoting quando si ricevono dati in formato ampio che richiedono la normalizzazione per l'analisi o quando si preparano i dati per i sistemi che richiedono un formato lungo.

Diagramma che illustra il processo di unpivot delle colonne in righe.

La UNPIVOT clausola trasforma le colonne specificate in coppie nome-valore. Si definisce una colonna per contenere i valori e un'altra per contenere i nomi delle colonne originali.

-- Create wide-format data
CREATE OR REPLACE TEMP VIEW regional_targets(region, jan, feb, mar, apr) AS
VALUES ('North', 50000, 55000, 52000, 58000),
       ('South', 45000, 48000, 51000, 53000),
       ('East',  60000, 62000, 65000, 68000);

-- Unpivot monthly columns into rows
SELECT *
FROM regional_targets
UNPIVOT (
  target_amount FOR month IN (jan, feb, mar, apr)
);

Il risultato converte ogni colonna del mese in righe:

region mese importo_target
A nord Gennaio 50000
A nord Febbraio 55000
A nord mar 52000
A nord Apr 58000
A sud Gennaio 45000
... ... ...

Per impostazione predefinita, UNPIVOT esclude i valori Null. Per includerli, specificare INCLUDE NULLS:

-- Unpivot while keeping null values
SELECT *
FROM regional_targets
UNPIVOT INCLUDE NULLS (
  target_amount FOR month IN (jan, feb, mar, apr)
);

È anche possibile assegnare alias personalizzati ai nomi di colonna non pivotate:

-- Unpivot with custom month labels
SELECT *
FROM regional_targets
UNPIVOT (
  target_amount FOR month IN (
    jan AS `January`,
    feb AS `February`,
    mar AS `March`,
    apr AS `April`
  )
);

Annotazioni

La UNPIVOT clausola richiede Databricks Runtime 12.2 LTS o versione successiva.

Scegliere la trasformazione corretta

Ogni trasformazione serve specifiche esigenze analitiche. Usare la denormalizzazione quando sono necessarie prestazioni di query veloci per dashboard e report. Scegliere la funzione "pivot" quando gli analisti necessitano di confronti paralleli tra le categorie. Applicare il processo di "unpivot" quando è necessario normalizzare i dati ampi per le pipeline di aggregazione o apprendimento automatico.

Queste trasformazioni spesso interagiscono tra loro nelle pipeline di dati. È possibile trasformare i dati di origine tramite un'operazione di unpivot per ristrutturare il formato, applicare trasformazioni e quindi eseguire un pivot per la presentazione finale, o denormalizzare l'output in tabelle ottimizzate per gli utenti finali.