28th Nov 2024 19 minutes de lecture Projet SQL pour les débutants : Tableau de bord des ventes AdventureWorks Ekre Ceannmor Projet SQL pratique sql Table des matières Exploration de la base de données AdventureWorks Définition de la portée de votre projet SQL Que comprendrons-nous dans notre tableau de bord de projet SQL ? Rapport 1 : Ventes mensuelles Question : Quel est le chiffre d'affaires de l'entreprise pour chaque mois ? Approche Rapport 2 : Recettes mensuelles par pays Question : Quel est le revenu mensuel pour chaque pays ? Approche Rapport 3 : Produits les plus vendus Question : Quels sont nos produits les plus vendus ? Approche Rapport 4 : Magasins les plus performants Question : Quels sont les 10 magasins les plus performants en termes de ventes au cours des deux derniers mois ? Approche Rapport 5 : Sources de revenus Question : Comment les revenus en ligne se comparent-ils aux revenus hors ligne ? Approche Rapport 6 : Taille moyenne des commandes par pays Question : Quel est le montant moyen des commandes ? Approche Rapport 6 : Valeur moyenne des clients à vie par région Question : Quelle est la valeur moyenne de la durée de vie des clients dans chaque région ? Approche Créez votre propre projet SQL pour les débutants ! Construire un projet SQL par soi-même est un excellent moyen d'affiner ses compétences et d'acquérir de l'expérience pratique. Cet exemple de projet SQL pour débutants vous montrera comment créer un tableau de bord des ventes avec SQL et la base de données d'exemple AdventureWorks. Si vous êtes un débutant en SQL et que vous souhaitez dépasser les simples exercices de requête, il est conseillé de vous attaquer à un projet d'analyse de données SQL. Non seulement vous serez amené à mettre en pratique ce que vous avez appris, mais vous comprendrez mieux comment SQL fonctionne dans des scénarios réels. C'est l'occasion de passer de la pratique de base à la création de quelque chose de tangible qui mettra en valeur votre expertise grandissante ! Dans cet article, nous allons vous guider à travers les étapes de la construction d'un projet SQL utilisant la base de données AdventureWorks. Nous aborderons toutes les étapes, de l'idée du projet à l'écriture des requêtes finales. Vous apprendrez comment aborder chaque étape du processus, et les concepts que nous utiliserons pourront être transférés à n'importe quel projet SQL. Une fois que vous aurez terminé, jetez un coup d'œil à notre cours Bases de données SQL pour la pratique, qui contient 6 bases de données différentes avec lesquelles vous pourrez vous entraîner à créer des rapports. Vous pouvez également lire comment trouver des ensembles de données gratuits pour votre propre projet SQL et suivre le cours avec votre propre base de données ! Jetons maintenant un coup d'œil à la base de données que nous allons utiliser dans cet exemple de projet SQL. Exploration de la base de données AdventureWorks La base de données AdventureWorks est une base de données échantillon créée par Microsoft pour SQL Server. Elle a été portée sur de nombreuses bases de données, y compris PostgreSQL, que nous utiliserons dans cet article. La base de données comprend 68 tables qui décrivent un fabricant fictif de bicyclettes et contient des données sur les différents types de transactions effectuées dans le cadre des activités de l'entreprise. La taille d'AdventureWorks en fait un ensemble de données idéal pour les débutants qui souhaitent s'exercer au langage SQL dans un contexte réel. La base de données est divisée en 5 schémas, chacun représentant un domaine d'activité différent : Production, Purchasing, Sales, HR, , et Person. Dans ce projet, la plupart de nos données proviendront du Sales . Nous utiliserons également d'autres schémas pour obtenir des informations supplémentaires. Examinons les tables que nous utiliserons le plus : SalesOrderHeader: C'est la plus grande table de la base de données. Elle stocke toutes les informations relatives à une commande dans son ensemble. C'est le point de départ le plus courant pour les requêtes relatives aux ventes. Product: Cette table contient de nombreuses informations sur les produits proposés par l'entreprise. SalesOrderDetail: Cette table relie les tables SalesOrderHeader et Product et stocke des informations sur les produits individuels qui composent chaque commande. ProductReview: Cette table stocke les avis des clients sur des produits spécifiques. Store: Ce tableau contient des informations de base sur chaque magasin. La plupart des données sont stockées dans la colonne Demographics au format XML ; nous ne l'utiliserons pas dans ce projet. SalesTerritory et CountryRegion: Nous utiliserons ces deux tables ensemble pour obtenir le nom du pays auquel la commande est associée. Il existe de nombreuses autres tables dans la base de données, mais ne vous inquiétez pas ; nous les présenterons, ainsi que leurs colonnes importantes, au fur et à mesure des besoins. Définition de la portée de votre projet SQL Dans ce projet, nous voulons créer un tableau de bord des ventes pour AdventureWorks. Mais comment commencer un tel projet ? Un bon point de départ consiste à déterminer l'étendue du projet. Souvent, cela implique de dresser une liste des questions auxquelles vous souhaitez répondre à l'aide des données. Notre liste de questions de départ est la suivante Quelles sont les ventes mensuelles totales ? Quelles sont les ventes mensuelles par pays ? Quels sont les produits les plus vendus ? Quels sont les magasins les plus performants ? Quel est le montant moyen de chaque commande ? Quelle est la valeur moyenne de la durée de vie d'un client dans chaque pays ? Au fur et à mesure que nous nous plongeons dans les données et que nous écrivons nos requêtes, nous pouvons affiner ces questions et ajuster nos requêtes en conséquence. C'est ainsi que vous devriez commencer tous vos projets SQL : dressez une liste des questions que vous vous posez sur les données, puis écrivez les requêtes qui vous donneront les réponses. Au fur et à mesure que vous travaillerez sur les requêtes et les données, de nouvelles questions apparaîtront. Essayez d'y répondre avec vos requêtes également. Nous sommes maintenant prêts à rédiger les requêtes pour notre tableau de bord des ventes ! Gardez notre feuille de contrôleSQL pour les débutants à portée de main au cas où vous auriez besoin d'un rafraîchissement rapide de la syntaxe. Que comprendrons-nous dans notre tableau de bord de projet SQL ? Rapport 1 : Ventes mensuelles Question : Quel est le chiffre d'affaires de l'entreprise pour chaque mois ? Le premier rapport de notre tableau de bord indique les revenus de tous les mois passés (pour chaque année). Cette requête peut être utilisée pour tracer des lignes de tendance en matière de revenus ou être analysée telle quelle. Nous souhaitons afficher les données par ordre chronologique, en commençant par les dates les plus récentes. Approche Tout d'abord, nous choisissons le tableau sur lequel notre requête sera basée. Nous souhaitons afficher trois colonnes : l'année et le mois de la vente et le revenu total pour ce mois et cette année. Nous avons besoin du montant total de la commande et de la date de la vente. SalesOrderHeader du schéma Sales est un choix évident. Pour afficher l'année et le mois, nous utiliserons la fonction EXTRACT: EXTRACT(<MONTH / YEAR> FROM OrderDate) Nous utiliserons ces colonnes pour grouper et ordonner les résultats. Pour obtenir le revenu total pour ce mois spécifique, nous pouvons utiliser SUM(TotalDue) en même temps que le regroupement par les deux colonnes précédentes. Nous obtiendrons ainsi des résultats SUM() distincts pour chaque paire année-mois unique. Voici la requête 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; Rapport 2 : Recettes mensuelles par pays Question : Quel est le revenu mensuel pour chaque pays ? Nous aimerions connaître le revenu total de chaque mois (de chaque année) pour chaque pays de la base de données. Les résultats doivent être triés par ordre chronologique, les dates les plus récentes apparaissant en premier. Nous pouvons utiliser ces données pour tracer des lignes de tendance pour chaque pays ou analyser les données telles quelles. Approche Cette requête est similaire à la précédente - il suffit d'ajouter des informations sur le pays pour chaque achat. Comment procéder ? La table SalesOrderHeader possède une colonne nommée TerritoryId, qui fait référence à la table SalesTerritory qui renvoie à la table Cette table nous donne accès à la colonne CountryRegionCode. Les noms de pays sont stockés dans la table CountryRegion du schéma Person . Nous pouvons joindre cette table à la table SalesTerritory en utilisant le code de la région. Nous disposons ainsi d'un moyen clair d'étendre notre requête. En joignant les tables comme suit : SalesOrderHeader -> SalesTerritory -> CountryRegion, nous avons accès à la colonne CountryRegion.Name. Nous pouvons l'ajouter comme première colonne dans l'instruction SELECT et l'ajouter à la fin des instructions GROUP BY et ORDER BY. Jetez un coup d'œil à la requête 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; Voici une partie du résultat : CountryOrderYearOrderMonthTotalRevenue Australia201469958.82 Canada2014611471.62 France201463660.88 Germany201463818.44 Rapport 3 : Produits les plus vendus Question : Quels sont nos produits les plus vendus ? Nous aimerions ajouter une liste des produits les plus vendus ainsi que des informations pertinentes telles que les ventes à vie et les avis des clients. Le rapport doit contenir des données relativement récentes. Approche Le tableau SalesOrderDetail qui contient la quantité de chaque article vendu, sera notre point de départ pour cette requête. Nous la construirons progressivement. La principale mesure de cette requête est la quantité totale vendue pour chaque produit, que nous pouvons obtenir en utilisant la combinaison de SUM(OrderQty) et GROUP BY ProductId. Cependant, le résultat de la requête serait assez difficile à lire, car les produits ne sont identifiables que par leur Id. Les noms des produits sont stockés dans la table Product du schéma Production . En joignant les deux tables à l'aide de ProductId et en ajoutant ProductName, nous obtenons cette requête : 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 Cette requête est un élément de tableau de bord viable, mais elle peut être améliorée. Nous avons déjà posé les bases pour travailler avec les produits. Nous voulons maintenant ajouter les évaluations à nos produits. Construisons une requête séparée, que nous joindrons plus tard à la requête principale. Les évaluations de produits sont stockées dans la table ProductReview de la table Production . Nous nous intéressons principalement aux notes ProductId et Rating laissées par le client, nous ferons donc la moyenne des notes et regrouperons les données par ProductId. Nous disposons à présent d'une correspondance univoque entre le produit et ses évaluations. Nous arrondissons le résultat à la première décimale, selon la méthode habituelle des évaluations : SELECT ProductId, ROUND(AVG(Rating), 1) AS ProductRating FROM Production.ProductReview GROUP BY ProductId; ProductIdProductRating 9373.0 7985.0 7095.0 Nous pouvons à présent intégrer cette requête dans une expression de table commune (CTE) à utiliser avec notre requête principale. Les CTE permettent de créer un ensemble de résultats temporaire, comme une table virtuelle qui n'existe que dans le contexte de la requête. Si vous souhaitez une explication complète du fonctionnement des CTE, consultez notre guide complet des CTE en SQL. Voici un problème possible : il se peut qu'il n'y ait pas d'avis pour tous les produits. Ainsi, lorsque nous joignons Product de la requête principale avec l'ETC, assurez-vous d'utiliser une adresse LEFT JOIN pour ne pas perdre de données. Il peut s'avérer utile de n'examiner que les données les plus récentes. Nous pouvons filtrer les anciennes ventes dans la requête principale à l'aide de la colonne OrderDate et soustraire deux mois de la date actuelle à l'aide de INTERVAL ‘2 MONTHS’. Nous pouvons ensuite filtrer les données pour n'afficher que les commandes passées après cette date. Si vous décidez de changer la plage de dates, il est très facile de modifier la partie INTERVAL. Pour en savoir plus sur la syntaxe INTERVAL, consultez notre coursFonctions SQL standards . Voici la requête complète : 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 Voilà une liste qui mérite d'être affichée sur le tableau de bord d'un représentant ! Comprendre les tendances des ventes est une chose à laquelle chaque employé devrait avoir accès - et nous disposons maintenant d'une requête qui le permet. Notre tableau de bord s'étoffe ; ajoutons d'autres mesures ! Rapport 4 : Magasins les plus performants Question : Quels sont les 10 magasins les plus performants en termes de ventes au cours des deux derniers mois ? Nous aimerions montrer les dix magasins les plus performants - y compris les magasins en ligne - et leur gain de chiffre d'affaires respectif au cours des deux derniers mois. Un "premier magasin" est défini comme celui qui a réalisé le plus de chiffre d'affaires au cours des deux derniers mois. Traitez tous les magasins en ligne comme une seule entité. Approche Comme d'habitude, nous commencerons par le tableau SalesOrderHeader tableau. Pour savoir quel magasin est responsable de quelle vente, examinons le tableau Store dans le schéma Sales . Chaque magasin peut être lié à une vente via la colonne SalesPersonId. Toutes les ventes pour lesquelles SalesPersonId est NULL ont également leur OnlineOrderFlag fixé à true. Cela facilitera le regroupement et l'affichage des ventes en ligne, car nous pouvons considérer toute vente où SalesPersonId est NULL comme une vente en ligne. Pour ne pas perdre de données lors de la jointure des tables sur SalesPersonId (qui est parfois NULL), utilisez un LEFT JOIN entre SalesOrderHeader et Store. Dans l'instruction SELECT, nous nous intéressons à deux choses : le nom du magasin et le total des ventes réalisées dans ce magasin. N'oubliez pas d'envelopper la colonne Store.Name avec COALESCE(..., ‘Online’) pour vous assurer que toutes les commandes en ligne ont une étiquette lisible. Pour filtrer les anciennes données, utilisez la même condition WHERE que dans le dernier rapport : WHERE OrderDate > CURRENT_DATE - INTERVAL ‘2 MONTHS’. Ordonnez les résultats en fonction du montant total des ventes (en affichant d'abord les valeurs les plus élevées) et utilisez LIMIT 10 pour ne renvoyer que les 10 premiers magasins par chiffre d'affaires au cours de la période sélectionnée. Voici la requête : 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 Rapport 5 : Sources de revenus Question : Comment les revenus en ligne se comparent-ils aux revenus hors ligne ? Pour cette mesure du tableau de bord, nous aimerions inclure des données sur le nombre de commandes passées en ligne par rapport au nombre de commandes passées en magasin. Les résultats finaux doivent être ventilés par mois et par année. Approche Une fois de plus, nous construirons cette requête de manière itérative. Pour diviser les ventes en groupes en ligne et hors ligne, nous pouvons utiliser le site OnlineOrderFlag de la table Sales.SalesOrderHeader de la table. Ce tableau comprend également le prix total de la commande, ce qui permet de calculer cette mesure à partir d'un seul tableau. Cependant, OnlineOrderFlag est un type de données BOOLEAN ; en l'utilisant dans la clause GROUP BY, nous nous retrouverons avec les groupes true et false. Pour rendre les données plus lisibles, nous pouvons utiliser une expression CASE WHEN pour remplacer tous les vrais par "Online" et tous les faux par "Store". Et comme l'expression OnlineOrderFlag est déjà évaluée à BOOLEAN, nous n'avons pas besoin de la modifier pour l'utiliser comme condition. Pour une explication plus approfondie de l'utilisation de CASE WHEN dans cet exemple, lisez notre guide sur l 'utilisation de CASE WHEN avec GROUP BY. Maintenant que nous disposons des noms de groupe appropriés, nous pouvons sélectionner les autres indicateurs qui comparent les sources de revenus : le nombre total d'affaires conclues et le revenu total de ces affaires. Vous pouvez trouver le premier en comptant simplement tous les SalesOrderIds et le second en additionnant toutes les valeurs TotalDue. Le regroupement peut être effectué à l'aide de OnlineOrderFlag et non de l'expression CASE WHEN; dans cette utilisation, nous ne faisons que mettre en correspondance des valeurs. Voici à quoi ressemble la requête actuelle : 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 Nous pouvons clairement voir une conclusion : Les magasins physiques réalisent presque 10 fois moins de ventes mais produisent 3 fois plus de revenus que les magasins en ligne. Nous pouvons rendre ces données plus significatives en les filtrant par année et par mois afin de voir les tendances dans les flux de revenus. Le tableau Sales.SalesOrderHeader comprend la colonne OrderDate, que nous pouvons utiliser pour obtenir uniquement les parties YEAR et MONTH, comme nous l'avons fait dans le premier rapport. Si nous ajoutons ces colonnes supplémentaires et les utilisons dans le tableau GROUP BY, nous verrons que les groupes “Store” et “Online” ont été divisés en différentes années et différents mois. Nous pouvons également filtrer les dates, comme nous l'avons fait précédemment avec CURRENT_DATE et INTERVAL. Voici la requête complète et un échantillon des résultats : 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 Rapport 6 : Taille moyenne des commandes par pays Question : Quel est le montant moyen des commandes ? Nous souhaitons afficher chaque pays et le montant moyen de toutes les commandes provenant de ce pays. Les pays dont le montant moyen des commandes est le plus élevé doivent être affichés en premier. Approche Nous avons déjà obtenu le nom du pays pour chaque vente dans l'un des rapports précédents, nous pouvons donc nous concentrer sur la taille des commandes. Il est important de noter que nous devrons effectuer deux agrégations dans cette requête : D'abord pour obtenir le montant de chaque commande, puis pour obtenir la moyenne par pays. Nous commencerons par obtenir la taille des commandes. Chaque commande peut être identifiée par une entrée dans la table SalesOrderHeader table. Elle aura plusieurs entrées respectives dans le tableau SalesOrderDetail correspondant à chaque produit de la commande. En additionnant les OrderQtys du tableau SalesOrderDetail pour chaque SalesOrderId, nous obtenons des paires numéro de commande - taille de la commande. Nous utiliserons quelques JOINs pour obtenir les noms de pays, en formant un CTE comme celui-ci : 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; Il ne reste plus qu'à obtenir la taille moyenne des commandes à partir de l'ETC et à regrouper les résultats par pays. N'oubliez pas d'ordonner les données de manière à afficher d'abord les commandes moyennes les plus importantes. Jetez un coup d'œil à la requête complète et à son résultat partiel : 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 Rapport 6 : Valeur moyenne des clients à vie par région Question : Quelle est la valeur moyenne de la durée de vie des clients dans chaque région ? La valeur à vie du client (CLV) est un indicateur important qui montre combien l'entreprise peut s'attendre à ce qu'un client nouvellement acquis dépense pendant toute la durée de sa relation avec la marque. La CLV est calculée en additionnant les revenus de tous les achats du client. Cette mesure est particulièrement utile pour calculer le budget des campagnes de marketing ; il est préférable de la présenter groupée par région d'activité. Approche Construisons d'abord la requête qui calcule la CLV moyenne pour chaque client individuellement. Nous savons déjà comment le CLV est calculé : en additionnant toutes les valeurs TotalDue pour chaque client de la table SalesOrderHeader pour chaque client. Cela nous donnera un résultat intermédiaire. Nous voulons ensuite les regrouper par pays, il est donc utile d'inclure certaines de ces données ici aussi. La table Customer dans le même schéma possède une colonne TerritoryId, que nous pourrons utiliser ultérieurement pour obtenir plus d'informations. Pour l'instant, ajoutons simplement TerritoryId à la requête CLV en tant que colonne supplémentaire. Cela nécessite une simple jointure et une extension de l'instruction GROUP BY. Voici à quoi ressemble la requête jusqu'à présent, ainsi que quelques exemples de résultats : 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 La moitié du problème est résolue. Il reste à regrouper les données au niveau des pays et à rendre le résultat plus lisible. Utilisons un CTE pour enregistrer les résultats de cette requête. Nous pouvons regrouper le CTE par TerritoryId et afficher la valeur moyenne de la durée de vie des clients par territoire. Le résultat est techniquement correct, mais les territoires ne sont pas identifiables. Les noms réels des pays sont stockés dans la table CountryRegion du schéma Person du schéma. Elle est identifiable par la clé CountryRegionCode. Dans le Sales nous pouvons trouver cette clé dans la table SalesTerritory table. Nous joindrons donc le résultat de l'ETC, par l'intermédiaire de la table SalesTerritory avec la table CountryRegion table. Nous pouvons maintenant afficher le nom du pays au lieu de son numéro Id. N'oubliez pas de modifier le site GROUP BY en conséquence. Jetez un coup d'œil à la requête finale et à certains de ses résultats : 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 Créez votre propre projet SQL pour les débutants ! Nous avons réussi à créer des requêtes qui peuvent alimenter un tableau de bord de vente informatif. Toutefois, cet article a pour but de vous inciter à lancer votre propre projet SQL. Récapitulons la procédure de création d'un projet SQL : Trouvez un ensemble de données intéressant. Trouvez un problème commercial pour cet ensemble de données, comme nous l'avons fait avec ce tableau de bord des ventes. Rédigez des questions liées à ce problème auxquelles le projet permettra de répondre. Construisez des requêtes SQL pour les questions que vous avez écrites. Si vous avez besoin d'un peu plus de structure, nous vous recommandons notre mini-cours SQL Databases for Practice. Il contient 6 bases de données différentes que vous pouvez utiliser dans votre propre projet SQL ainsi que quelques questions et suggestions pour vous aider à démarrer. Si vous souhaitez voir d'autres exemples de projets SQL pour débutants, consultez notre article sur la création d'un projet Northwind Store pour votre portfolio. Vous avez envie de plus de pratique générale ? Consultez notre énorme piste La pratique du SQL . Bon apprentissage ! Tags: Projet SQL pratique sql