Torna all'elenco degli articoli Articoli
Tempo di lettura: 17 minuti

Progetto SQL per principianti: Cruscotto vendite AdventureWorks

Costruire un progetto SQL per conto proprio è un ottimo modo per affinare le proprie capacità e fare esperienza pratica. Questo esempio di progetto SQL per principianti vi mostrerà come creare un cruscotto di vendita con SQL e il database di esempio AdventureWorks.

Se siete principianti dell'SQL e volete andare oltre i semplici esercizi di query, è una buona idea affrontare un progetto di analisi dei dati SQL. Non solo vi sfiderà ad applicare ciò che avete imparato, ma vi darà anche una comprensione più profonda di come SQL funziona in scenari reali. Questa è l'occasione per passare dalla pratica di base alla creazione di qualcosa di tangibile che mostri la vostra crescente esperienza!

In questo articolo vi guideremo attraverso le fasi di costruzione di un progetto SQL utilizzando il database AdventureWorks. Ci occuperemo di tutto, dall'idea del progetto alla scrittura delle query finali. Imparerete come affrontare ogni fase del processo e i concetti che utilizzeremo potranno essere trasferiti a qualsiasi progetto SQL.

Una volta terminato, date un'occhiata al nostro corso SQL Databases for Practice, che contiene 6 diversi database con cui potrete esercitarvi a creare report. In alternativa, potete leggere come trovare set di dati gratuiti per il vostro progetto SQL e seguire il corso con il vostro database!

Ora diamo un'occhiata al database che utilizzeremo in questo progetto di esempio SQL.

Esplorazione del database AdventureWorks

Il database AdventureWorks è un database di esempio creato da Microsoft per SQL Server. È stato portato su molti database, tra cui PostgreSQL, che utilizzeremo in questo articolo. Il database comprende 68 tabelle che descrivono un produttore di biciclette immaginario e contiene dati sui diversi tipi di transazioni che avvengono durante le operazioni commerciali. Poiché AdventureWorks è così grande, è un set di dati perfetto per i principianti che vogliono fare pratica con l'SQL in un contesto reale.

Il database è suddiviso in 5 schemi, ognuno dei quali rappresenta un diverso campo di operazioni: Production, Purchasing, Sales, HR, e Person. In questo progetto, la maggior parte dei dati proverrà dallo Sales schema. Utilizzeremo anche altri schemi per ottenere alcune informazioni aggiuntive.

Vediamo le tabelle che utilizzeremo di più:

: Cruscotto vendite AdventureWorks
  • SalesOrderHeader: È la tabella più grande del database. Memorizza tutte le informazioni relative a un ordine nel suo complesso. Sarà il punto di partenza più comune per le interrogazioni relative alle vendite.
  • Product: Memorizza informazioni complete sui prodotti offerti dall'azienda.
  • SalesOrderDetail: Questa tabella collega le tabelle SalesOrderHeader e Product memorizzando le informazioni sui singoli prodotti che compongono ogni ordine.
  • ProductReview: Memorizza le recensioni dei clienti su prodotti specifici.
  • Store: Questa tabella contiene informazioni di base su ogni negozio. La maggior parte dei dati è memorizzata nella colonna Demographics in formato XML; non la utilizzeremo in questo progetto.
  • SalesTerritory e CountryRegion: Utilizzeremo queste due tabelle insieme per ottenere il nome del Paese a cui è associato l'ordine.

Esistono molte altre tabelle nel database, ma non preoccupatevi; le presenteremo e le loro colonne importanti quando sarà necessario.

Definizione del progetto SQL

In questo progetto vogliamo creare un cruscotto di vendita per AdventureWorks. Ma come si inizia un progetto del genere? Un ottimo punto di partenza è determinare l'ambito del progetto. Spesso questo significa creare un elenco di domande a cui si vuole rispondere con i dati. Il nostro elenco iniziale di domande è:

  • Quali sono le vendite totali mensili?
  • Quali sono le vendite mensili per Paese?
  • Quali sono i prodotti più venduti?
  • Quali sono i negozi che ottengono i risultati migliori?
  • Qual è la dimensione media di ogni ordine?
  • Qual è il valore medio di vita del cliente in ogni Paese?

Man mano che ci immergiamo nei dati e scriviamo le nostre query, possiamo affinare queste domande e aggiustare le nostre query di conseguenza.

Questo è il modo in cui dovreste iniziare tutti i vostri progetti SQL: scrivete un elenco delle domande che avete sui dati e poi scrivete le query che vi daranno le risposte. Man mano che si lavora sulle query e sui dati, emergeranno nuove domande. Cercate di rispondere anche a queste con le vostre query.

Ora siamo pronti per iniziare a scrivere le query per il nostro dashboard delle vendite! Tenete a portata di mano il nostro SQL per principianti Cheat Sheet nel caso in cui abbiate bisogno di un rapido ripasso della sintassi.

Che cosa includeremo nel nostro dashboard del progetto SQL?

Rapporto 1: Vendite mensili

Domanda: Qual è il fatturato dell'azienda per ogni mese?

Il primo report del nostro dashboard mostra le entrate di tutti i mesi passati (per ogni anno). Questa query può essere utilizzata per tracciare linee di tendenza delle entrate, oppure può essere analizzata così com'è. Vogliamo visualizzare i dati in ordine cronologico, partendo dalle date più recenti.

Approccio

Innanzitutto, scegliamo la tabella su cui basare la nostra query. Vogliamo visualizzare tre colonne: l'anno e il mese di vendita e il fatturato totale per quel mese e quell'anno. Abbiamo bisogno dell'importo totale dell'ordine e della data di vendita, quindi la tabella SalesOrderHeader dello schema Sales è una scelta ovvia.

Per visualizzare l'anno e il mese, utilizzeremo la funzione EXTRACT:

EXTRACT(<MONTH / YEAR> FROM OrderDate)

Utilizzeremo queste colonne per raggruppare e ordinare i risultati.

Per ottenere le entrate totali per quel mese specifico, possiamo usare SUM(TotalDue) insieme al raggruppamento per le due colonne precedenti. In questo modo avremo risultati SUM() separati per ogni coppia anno-mese.

Ecco la query finale:

SELECT
  EXTRACT(YEAR FROM OrderDate) AS OrderYear,
  EXTRACT(MONTH FROM OrderDate) AS OrderMonth,
  ROUND(SUM(TotalDue), 2) AS TotalRevenue
FROM Sales.SalesOrderHeader
GROUP BY 
  EXTRACT(YEAR FROM OrderDate),
  EXTRACT(MONTH FROM OrderDate)
ORDER BY 
  OrderYear DESC,
  OrderMonth DESC;

Report 2: Fatturato mensile per Paese

Domanda: Qual è il fatturato mensile per ogni Paese?

Vorremmo vedere le entrate totali per ogni mese (di ogni anno) per ogni paese del database. Il risultato dovrebbe essere ordinato in ordine cronologico, con le date più recenti al primo posto. Possiamo utilizzare questi dati per tracciare linee di tendenza per ogni paese o analizzare i dati così come sono.

Approccio

Questa query è simile alla precedente: dobbiamo solo aggiungere le informazioni sul paese per ogni acquisto. Come possiamo farlo?

La tabella SalesOrderHeader ha una colonna denominata TerritoryId, che fa riferimento alla tabella SalesTerritory tabella. Questa tabella ci dà accesso alla colonna CountryRegionCode.

I nomi dei Paesi sono memorizzati nella tabella CountryRegion dello schema Person dello schema. Possiamo unire questa tabella alla tabella SalesTerritory utilizzando il codice della regione. In questo modo abbiamo un modo chiaro per espandere la nostra query.

Unendo le tabelle in questo modo SalesOrderHeader -> SalesTerritory -> CountryRegion si ha accesso alla colonna CountryRegion.Name. Possiamo aggiungerla come prima colonna nell'istruzione SELECT e aggiungerla alla fine di GROUP BY e ORDER BY.

Osservate la query finale:

SELECT
  cr.Name AS Country,
  EXTRACT(YEAR FROM OrderDate) AS OrderYear,
  EXTRACT(MONTH FROM OrderDate) AS OrderMonth,
  ROUND(SUM(TotalDue), 2) AS TotalRevenue
FROM Sales.SalesOrderHeader soh
JOIN Sales.SalesTerritory st
  ON soh.TerritoryId = st.TerritoryId
JOIN Person.CountryRegion cr
  ON cr.CountryRegionCode = st.CountryRegionCode
GROUP BY 
  cr.Name,
  EXTRACT(YEAR FROM OrderDate),
  EXTRACT(MONTH FROM OrderDate)
ORDER BY
  OrderYear DESC,
  OrderMonth DESC,
  Country;

Ecco una parte dell'output:

CountryOrderYearOrderMonthTotalRevenue
Australia201469958.82
Canada2014611471.62
France201463660.88
Germany201463818.44

Rapporto 3: Prodotti più venduti

Domanda: Quali sono i nostri prodotti più venduti?

Vorremmo aggiungere un elenco dei prodotti più venduti insieme ad alcune informazioni rilevanti come le vendite e le recensioni dei clienti. Il report dovrebbe mostrare dati ragionevolmente recenti.

Approccio

La tabella SalesOrderDetail che contiene la quantità di ogni articolo venduto, sarà il nostro punto di partenza per questa query. La costruiremo in modo incrementale.

La metrica principale di questa query è la quantità totale venduta per ogni prodotto, che possiamo ottenere utilizzando la combinazione di SUM(OrderQty) e GROUP BY ProductId.

Tuttavia, il risultato della query sarebbe piuttosto difficile da leggere, in quanto i prodotti sono identificabili solo attraverso il loro Id. I nomi dei prodotti sono memorizzati nella tabella Product dello schema Production schema. Unendo le due tabelle con ProductId e aggiungendo ProductName si ottiene questa query:

SELECT
  p.ProductId,
  p.Name AS ProductName,
  SUM(od.OrderQty) AS TotalUnitsSold
FROM Sales.SalesOrderDetail od
JOIN Production.Product p
  ON od.ProductID = p.ProductID
GROUP BY
  p.Name,
  p.ProductId
ORDER BY TotalUnitsSold DESC
LIMIT 10;
ProductIdProductNameTotalUnitsSold
712AWC Logo Cap8311
870Water Bottle - 30 oz.6815

Questa query è un elemento valido del dashboard, ma può essere migliorata.

Abbiamo già gettato le basi per lavorare con i prodotti. Ora vogliamo aggiungere le valutazioni ai nostri prodotti. Costruiamo una query separata, che poi uniremo alla query principale.

Le recensioni dei prodotti sono memorizzate nella tabella ProductReview della tabella Production schema. A noi interessano soprattutto le ProductId e le Rating lasciate dal cliente, quindi faremo una media dei punteggi di valutazione e raggrupperemo i dati per ProductId.

Ora abbiamo una mappatura uno-a-uno tra il prodotto e le sue valutazioni. Arrotondiamo il risultato a una cifra decimale, come di consueto per le recensioni:

SELECT
  ProductId,
  ROUND(AVG(Rating), 1) AS ProductRating
FROM Production.ProductReview
GROUP BY ProductId;
ProductIdProductRating
9373.0
7985.0
7095.0

Ora possiamo trasformare questa query in una Common Table Expression (CTE) da usare insieme alla nostra query principale. Le CTE sono un modo per creare un insieme di risultati temporaneo, come una tabella virtuale che esiste solo nel contesto della query. Se volete una spiegazione completa del funzionamento delle CTE, consultate la nostra guida completa alle CTE in SQL.

Ora, c'è un possibile problema: potrebbero non esserci recensioni per tutti i prodotti. Quindi, quando uniamo Product dalla query principale con la CTE, assicurarsi di utilizzare un LEFT JOIN per non perdere alcun dato.

Potrebbe essere utile esaminare solo i dati più recenti. Possiamo filtrare le vecchie vendite nella query principale usando la colonna OrderDate e sottrarre due mesi dalla data corrente usando INTERVAL ‘2 MONTHS’. Quindi è possibile filtrare i dati per mostrare solo gli ordini effettuati dopo tale data.

Se si decide di cambiare l'intervallo di date, modificare la parte INTERVAL è abbastanza semplice. Per saperne di più sulla sintassi di INTERVAL, date un'occhiata al corsoFunzioni SQL standard .

Questa è la query completa:

WITH ProductRating AS (
  SELECT
    ProductId,
    ROUND(AVG(Rating), 1) AS ProductRating
  FROM Production.ProductReview
  GROUP BY ProductId
)
SELECT
  p.ProductId,
  p.Name AS ProductName,
  SUM(od.OrderQty) AS TotalUnitsSold,
  pr.ProductRating AS ProductRating
FROM Sales.SalesOrderDetail od
JOIN Sales.SalesOrderHeader oh
  ON od.SalesOrderId = oh.SalesOrderId
JOIN Production.Product p
  ON od.ProductID = p.ProductID
LEFT JOIN ProductRating pr
  ON pr.ProductId = p.ProductId
WHERE OrderDate > CURRENT_DATE - INTERVAL '2 MONTH'
GROUP BY
  p.Name,
  p.ProductId,
  pr.ProductRating
ORDER BY TotalUnitsSold DESC
LIMIT 10;
ProductIdProductNameTotalUnitsSoldProductRating
921Mountain Tire Tube187N/A
873Patch Kit / 8 Patches181N/A
870Water Bottle - 30 oz.168N/A
922Road Tire Tube160N/A
878Fender Set - Mountain107N/A
711Sport-100 Helmet, Blue96N/A
712AWC Logo Cap95N/A
708Sport-100 Helmet, Black93N/A
923Touring Tire Tube91N/A
871Mountain Bottle Cage84N/A

Questo è un elenco degno di essere visualizzato sul cruscotto di un rappresentante! La comprensione delle tendenze di vendita è qualcosa a cui ogni dipendente dovrebbe avere accesso e ora abbiamo una query che ce la fornisce.

Il nostro cruscotto sta crescendo; aggiungiamo altre metriche!

Rapporto 4: Negozi più performanti

Domanda: Quali sono i 10 negozi più venduti negli ultimi 2 mesi?

Vorremmo mostrare i primi dieci negozi, compresi quelli online, e il rispettivo aumento dei ricavi negli ultimi due mesi. Per "top store" si intende quello che ha registrato il maggior fatturato negli ultimi 2 mesi. Considerare tutti i negozi online come un'unica entità.

Approccio

Come di consueto, si parte dalla tabella SalesOrderHeader tabella. Per scoprire quale negozio è responsabile di una determinata vendita, osserviamo la tabella Store nello schema Sales dello schema.

Ogni negozio può essere collegato a una vendita tramite la colonna SalesPersonId. Tutte le vendite in cui SalesPersonId è NULL hanno anche OnlineOrderFlag impostato su true. Questo semplificherà il lavoro di raggruppamento e di visualizzazione delle vendite online, in quanto possiamo considerare ogni vendita in cui SalesPersonId è NULL come una vendita online.

Per non perdere i dati quando si uniscono le tabelle su SalesPersonId (che a volte è NULL), utilizzare un LEFT JOIN tra SalesOrderHeader e Store. Nell'istruzione SELECT ci interessano due cose: il nome del negozio e il totale delle vendite effettuate in quel negozio. Non dimenticate di avvolgere la colonna Store.Name con COALESCE(..., ‘Online’) per assicurarvi che tutti gli ordini online abbiano un'etichetta leggibile.

Per filtrare i dati vecchi, utilizzare la stessa condizione WHERE dell'ultimo report:

WHERE OrderDate > CURRENT_DATE - INTERVAL ‘2 MONTHS’.

Ordinare i risultati in base all'importo totale delle vendite (mostrando prima i valori più grandi) e utilizzare LIMIT 10 per restituire solo i primi 10 negozi per fatturato nel periodo selezionato.

Ecco la query:

SELECT
  COALESCE(s.Name, 'Online') AS StoreName,
  ROUND(SUM(so.TotalDue), 2) AS TotalSalesAmount
FROM Sales.SalesOrderHeader so
LEFT JOIN Sales.Store s
  ON so.SalesPersonId = s.SalesPersonId
WHERE OrderDate > CURRENT_DATE - INTERVAL '2 MONTHS'
GROUP BY s.Name
ORDER BY TotalSalesAmount DESC
LIMIT 10;
StoreNameTotalSalesAmount
Online2419079.86
Friendly Bike Shop577136.64
Exceptional Cycles Services495918.62
Number One Bike Co.495918.62

Rapporto 5: Fonti di fatturato

Domanda: Come si confrontano le entrate online con quelle offline?

Per questa metrica del dashboard, vorremmo includere i dati relativi al numero di ordini effettuati online rispetto a quelli effettuati in negozio. I risultati finali dovrebbero essere suddivisi per mese e anno.

Approccio

Ancora una volta, costruiremo questa query in modo iterativo. Per suddividere le vendite in gruppi online e offline, si può utilizzare la tabella OnlineOrderFlag. Sales.SalesOrderHeader della tabella. Questa tabella include anche il prezzo totale dell'ordine, quindi questa metrica può essere calcolata da un'unica tabella.

Tuttavia, il dato OnlineOrderFlag è di tipo BOOLEAN; se lo si utilizza nella clausola GROUP BY si avranno i gruppi true e false. Per rendere i dati più leggibili, possiamo usare un'espressione CASE WHEN per sostituire tutti i veri con "Online" e tutti i falsi con "Store". Poiché l'espressione OnlineOrderFlag ha già come risultato BOOLEAN, non è necessario modificarla per utilizzarla come condizione. Per una spiegazione più approfondita di come stiamo usando CASE WHEN in questo esempio, leggete la nostra guida su come usare CASE WHEN con GROUP BY.

Ora che i nomi dei gruppi sono corretti, possiamo selezionare le altre metriche che mettono a confronto le fonti di guadagno: il numero totale di transazioni chiuse e il ricavo totale di tali transazioni. Il primo si ottiene semplicemente contando tutti i SalesOrderIds e il secondo sommando tutti i valori di TotalDue. Il raggruppamento può essere fatto usando il semplice OnlineOrderFlag e non l'espressione CASE WHEN; in questo caso, stiamo semplicemente mappando i valori.

Ecco come appare la query attuale:

SELECT
  CASE WHEN OnlineOrderFlag THEN 'Online' ELSE 'Store' END AS OrderOrigin,
  COUNT(SalesOrderId) AS TotalSales,
  SUM(TotalDue) AS TotalRevenue
FROM Sales.SalesOrderHeader
GROUP BY OnlineOrderFlag
ORDER BY TotalRevenue DESC;
OrderOriginTotalSalesTotalRevenue
Online276593244139
Store380690775446

Possiamo vedere chiaramente una conclusione: I negozi fisici realizzano quasi 10 volte meno vendite ma producono 3 volte più ricavi dei negozi online.

Possiamo rendere questi dati più significativi filtrandoli per anno e mese, in modo da vedere le tendenze dei flussi di entrate. La tabella Sales.SalesOrderHeader include la colonna OrderDate, che possiamo utilizzare per ottenere solo le parti YEAR e MONTH come abbiamo fatto nel primo report. Se aggiungiamo queste colonne supplementari e le utilizziamo in GROUP BY, vedremo che i gruppi “Store” e “Online” sono stati suddivisi in anni e mesi diversi. Possiamo inoltre filtrare le date, come abbiamo fatto in precedenza con CURRENT_DATE e INTERVAL.

Ecco la query completa e un esempio dei risultati:

SELECT
  CASE WHEN OnlineOrderFlag THEN 'Online' ELSE 'Store' END AS OrderOrigin,
  EXTRACT(YEAR FROM OrderDate) AS OrderYear,
  EXTRACT(MONTH FROM OrderDate) AS OrderMonth,
  COUNT(SalesOrderId) AS TotalSales,
  SUM(TotalDue) AS totalRevenue
FROM Sales.SalesOrderHeader
WHERE OrderDate > CURRENT_DATE - INTERVAL '2 MONTHS'
GROUP BY
  EXTRACT(YEAR FROM OrderDate),
  EXTRACT(MONTH FROM OrderDate),
  OnlineOrderFlag
ORDER BY
  OrderOrigin,
  OrderYear DESC,
  OrderMonth DESC;
OrderOriginOrderYearOrderMonthTotalSalesTotalRevenue
Online2014693954151,48
Store20145125843850111,69
Online201454062156071,52
Store2014421428,61

Rapporto 6: Dimensione media degli ordini per Paese

Domanda: Qual è la dimensione media dell'ordine?

Vorremmo visualizzare ogni paese e la dimensione media dell'ordine per tutti gli ordini provenienti da quel paese. I Paesi con una dimensione media dell'ordine maggiore dovrebbero essere mostrati per primi.

Approccio

Abbiamo già ottenuto il nome del Paese per ogni vendita in uno dei report precedenti, quindi possiamo concentrarci sulle dimensioni degli ordini. È importante notare che in questa query dovremo aggregare due volte: Prima per ottenere la dimensione dell'ordine per ogni ordine e poi per ottenere la media del Paese. Cominciamo con le dimensioni degli ordini.

Ogni ordine può essere identificato da una voce nella tabella SalesOrderHeader tabella. Avrà più voci rispettive nella tabella SalesOrderDetail tabella corrispondenti a ciascun prodotto dell'ordine. Sommando le OrderQtys dalla tabella SalesOrderDetail per ogni SalesOrderId si ottengono le coppie numero_ordine-dimensione_ordine.

Utilizzeremo un paio di JOINs per ottenere i nomi dei paesi, formando una CTE come questa:

WITH OrderSizes AS (
  SELECT
    sod.SalesOrderId,
    SUM(OrderQty) AS ProductCount,
    cr.Name AS Country
  FROM Sales.SalesOrderHeader soh
  JOIN Sales.SalesOrderDetail sod
    ON sod.SalesOrderId = soh.SalesOrderId
  JOIN Sales.SalesTerritory st
    ON soh.TerritoryId = st.TerritoryId
  JOIN Person.CountryRegion cr
    ON cr.CountryRegionCode = st.CountryRegionCode
  GROUP BY
    sod.SalesOrderId,
    cr.Name
)
SELECT * 
FROM OrderSizes;

Ora si tratta solo di ottenere la dimensione media degli ordini dalla CTE e di raggruppare il risultato per paese. Non dimenticate di ordinare i dati in modo da mostrare prima le dimensioni medie degli ordini più grandi.

Date un'occhiata alla query completa e al suo risultato parziale:

WITH OrderSizes AS (
  SELECT
    sod.SalesOrderId,
    SUM(OrderQty) AS ProductCount,
    cr.Name AS Country
  FROM Sales.SalesOrderHeader soh
  JOIN Sales.SalesOrderDetail sod
    ON sod.SalesOrderId = soh.SalesOrderId
  JOIN Sales.SalesTerritory st
    ON soh.TerritoryId = st.TerritoryId
  JOIN Person.CountryRegion cr
    ON cr.CountryRegionCode = st.CountryRegionCode
  GROUP BY
    sod.SalesOrderId,
    cr.Name
)
SELECT
  Country,
  ROUND(AVG(ProductCount), 2) AS AverageOrderSize
FROM OrderSizes
GROUP BY Country
ORDER BY AverageOrderSize DESC;
CountryAverageOrderSize
United States12.80
Canada12.14
France7.45
United Kingdom6.24
Germany5.01
Australia2.67

Report 6: Valore medio dei clienti a vita per regione

Domanda: Qual è il valore medio della vita del cliente in ogni regione?

Il Customer Lifetime Value (CLV) è una metrica importante che mostra quanto l'azienda può aspettarsi che un nuovo cliente acquisito spenda durante l'intero rapporto con il marchio. Il CLV si calcola sommando i ricavi di tutti gli acquisti del cliente. È molto utile per calcolare il budget per le campagne di marketing; è meglio mostrarlo raggruppato per regione di attività.

Approccio

Costruiamo innanzitutto la query che calcola il CLV medio per ogni singolo cliente. Sappiamo già come viene calcolato il CLV: sommando tutti i valori di TotalDue per ogni cliente della tabella. SalesOrderHeader tabella. Questo ci darà un risultato intermedio. In seguito vogliamo raggruppare i dati per paese, quindi è utile includere anche alcuni di questi dati.

La tabella Customer nello stesso schema ha una colonna TerritoryId, che possiamo utilizzare in seguito per ottenere ulteriori informazioni. Per ora, aggiungiamo TerritoryId alla query CLV come colonna aggiuntiva. Questo richiede un semplice join e un'espansione dell'istruzione GROUP BY.

Ecco come appare la query finora, insieme ad alcuni risultati di esempio:

SELECT
  cs.CustomerId,
  cs.TerritoryId,
  SUM(TotalDue) AS LifetimeRevenues
FROM sales.Customer cs
JOIN sales.SalesOrderheader ord
  ON cstm.CustomerId = ord.CustomerId
GROUP BY
  cs.CustomerId,
  cs.TerritoryId;
CustomerIdTerritoryIdLifetimeRevenue
26264434.56
30052421863.90
244161106.16
2674592135.37

Metà del problema è risolto. Ciò che resta da fare è raggruppare il tutto a livello di Paese e rendere il risultato più leggibile. Utilizziamo una CTE per salvare i risultati della query.

Possiamo raggruppare la CTE per TerritoryId e mostrare il valore di vita medio dei clienti per territorio. Il risultato è tecnicamente corretto, anche se i territori non sono identificabili. I nomi effettivi dei paesi sono memorizzati nella tabella CountryRegion dello schema Person dello schema. È identificabile dalla chiave CountryRegionCode. Nello Sales possiamo trovare questa chiave nella tabella SalesTerritory tabella. Quindi, uniremo il risultato della CTE, attraverso la tabella SalesTerritory con la tabella CountryRegion tabella. Ora possiamo mostrare il nome del Paese invece del suo numero Id. Non dimenticare di modificare di conseguenza GROUP BY.

Date un'occhiata alla query finale e ad alcuni dei suoi risultati:

WITH CustomerLifetimeRevenue AS (
  SELECT
    cstm.CustomerId,
    ord.TerritoryId,
    SUM(TotalDue) AS LifetimeRevenue
  FROM Sales.Customer cstm
  JOIN Sales.SalesOrderHeader ord
    ON cstm.CustomerId = ord.CustomerId
  GROUP BY
    cstm.CustomerId,
    ord.TerritoryId
)
SELECT
  cr.Name AS Country,
  ROUND(AVG(clr.LifetimeRevenue),2) AS AvgLifetimeCustomerValue
FROM CustomerLifetimeRevenue clr
JOIN Sales.SalesTerritory tr
  ON clr.TerritoryId = tr.TerritoryId
JOIN Person.CountryRegion cr
  ON cr.CountryRegionCode = tr.CountryRegionCode
GROUP BY cr.Name
ORDER BY
  AvgLifetimeCustomerValue DESC,
  cr.Name;
CountryAvgLifetimeCustomerValue
Canada10971.34
United States8627.27
France4403.33
United Kingdom4394.69
Australia3259.14
Germany3024.18

Crea il tuo progetto SQL per principianti!

Abbiamo creato con successo query in grado di alimentare un dashboard di vendita ricco di informazioni. Tuttavia, questo articolo ha lo scopo di ispirarvi a iniziare il vostro progetto SQL. Riassumiamo come creare un progetto SQL:

  • Trovare un set di dati interessante.
  • Cercate un problema di business per questo set di dati, come abbiamo fatto con questo cruscotto di vendita.
  • Scrivere le domande relative al problema a cui il progetto aiuterà a rispondere.
  • Creare query SQL per le domande scritte.

Se avete bisogno di un po' più di struttura, vi consigliamo il nostro mini-corso SQL Databases for Practice. Contiene 6 diversi database che potete utilizzare nel vostro progetto SQL, oltre ad alcune domande e suggerimenti per iniziare.

Se volete vedere altri esempi di progetti SQL per principianti, date un'occhiata al nostro articolo sulla creazione di un progetto Northwind Store per il vostro portfolio.

Volete fare più pratica? Date un'occhiata alla nostra enorme tracciaPratica su SQL . Buon apprendimento!