Retour à la liste des articles Articles
21 minutes de lecture

Pratique SQL pour les débutants : Exercices AdventureWorks

Table des matières

Améliorez vos compétences SQL grâce à des exercices pratiques utilisant la base de données d'exemple d'AdventureWorks. Pratiquez les fonctions SQL essentielles à l'aide de scénarios réels.

Il est important de pratiquer le langage SQL si l'on veut améliorer son utilisation. Cet article propose 20 exercices pour débutants utilisant la base de données d'exemple AdventureWorks de Microsoft. Cette base de données est conçue pour montrer comment fonctionne le serveur SQL. Elle représente une entreprise fictive de fabrication de bicyclettes appelée AdventureWorks Cycles et comprend cinq schémas : Ressources humaines, Personnes, Production, Achats et Ventes. Elle est donc idéale pour apprendre et pratiquer le langage SQL.

La base de données AdventureWorks couvre différents scénarios commerciaux tels que la fabrication, les ventes, les achats, la gestion des produits, la gestion des contacts et les ressources humaines. Elle constitue donc une excellente ressource pour l'apprentissage et la pratique du langage SQL, car elle offre un large éventail de données et de processus d'entreprise avec lesquels il est possible de travailler. En vous exerçant avec cette base de données, vous pouvez acquérir une expérience pratique avec des données et des scénarios du monde réel ; cela vous aidera à comprendre comment écrire des requêtes efficaces et résoudre efficacement des problèmes de données.

Si vous souhaitez essayer d'autres exemples de bases de données, consultez notre liste des sources de données les plus intéressantes pour la pratique du langage SQL. Cependant, la mise en place de votre propre environnement de pratique SQL peut prendre du temps. Pour une pratique rapide, essayez notre pisteLa pratique du SQL ou nos bases de données de pratique SQL. Nous publions également un cours SQL gratuit par mois pour vous aider à continuer à apprendre.

Maintenant, commençons à pratiquer SQL avec les exercices d'AdventureWorks !

Examen de la base de données AdventureWorks

La base de données AdventureWorks comprend cinq schémas de base de données (c'est-à-dire des structures de base de données utilisées pour regrouper des tables de données), notamment HumanResources, Person, Production, Purchasing et Sales. Dans les exercices suivants, nous utiliserons le schéma HumanResources.

Commençons par analyser le schéma :

Base de données AdventureWorks

Tout d'abord, passons en revue les concepts de clés primaires et étrangères :

  • La clé primaire (PK) est une colonne (ou un ensemble de colonnes) qui identifie de manière unique chaque ligne d'une table. Par exemple, la colonne BusinessEntityID est la clé primaire de la table Employee car chaque employé se voit attribuer un numéro d'identification unique.
  • La clé étrangère (CE) est une colonne (ou un ensemble de colonnes) qui relie deux tables. Notez que la clé étrangère d'une table est la clé primaire d'une autre table - sur cette base, les deux tables sont liées. Par exemple, la colonne BusinessEntityID est la clé primaire de la table Employee et également une clé étrangère dans la table JobCandidate et une clé étrangère dans la table Elle relie les deux tables et permet à la table JobCandidate de se référer aux lignes de la table Employee

Analysons maintenant les tables du schéma.

La table Employee stocke des informations sur les employés et constitue la table principale de ce schéma. Elle est liée aux tables suivantes :

  • La table JobCandidate stocke les CV des candidats à l'emploi. La colonne BusinessEntityID est un PK dans la table Employee et un FK dans la table JobCandidate Le PK de la table JobCandidate est la colonne JobCandidateID.
  • La table EmployeePayHistory stocke l'historique des taux de rémunération des employés. La colonne BusinessEntityID est un PK dans la table Employee et un FK dans la table EmployeePayHistory Notez que la colonne BusinessEntityID de la table EmployeePayHistory est à la fois un FK et une partie du PK. Le PK du tableau EmployeePayHistory comprend les colonnes BusinessEntityID et RateChangeDate. C'est ce qu'on appelle une clé primaire composite.
  • La table EmployeeDepartmentHistory stocke l'historique des départements des employés. La colonne BusinessEntityID est un PK dans la table Employee et une FK dans la table EmployeeDepartmentHistory Notez que la colonne BusinessEntityID de la table EmployeeDepartmentHistory est à la fois un FK et une partie du PK. La PK de la table EmployeeDepartmentHistory comprend les colonnes BusinessEntityID, DepartmentID, ShiftID et StartDate. Il s'agit d'une autre clé primaire composite.

La table EmployeeDepartmentHistory stocke des informations sur les employés et leurs départements au fil du temps et peut être considérée comme une autre table principale de ce schéma. Elle est liée aux tables suivantes :

  • La table Shift stocke des informations sur les équipes disponibles. La colonne ShiftID est un PK dans la table Shift et un FK dans la table EmployeeDepartmentHistory Notez que la colonne ShiftID est à la fois un FK et une partie du PK dans la table EmployeeDepartmentHistory dans la table.
  • La table Department stocke des informations sur les départements. La colonne DepartmentID est un PK dans la table Department et un FK dans la table EmployeeDepartmentHistory Notez que la colonne DepartmentID est à la fois un FK et une partie du PK dans la table EmployeeDepartmentHistory de la table.

Nous sommes maintenant prêts à commencer nos exercices AdventureWorks.

Exercices AdventureWorks pour les débutants

Au fil de cet article, nous aborderons toutes les bases du langage SQL (ainsi que quelques fonctions avancées) :

  • Requêtes sur une seule table pour extraire et filtrer des données.
  • Les requêtes sur plusieurs tables qui utilisent les JOIN pour combiner les données de deux tables ou plus.
  • Le regroupement et l'agrégation de données pour effectuer des opérations mathématiques sur des données sélectionnées.
  • D'autres fonctionnalités SQL pertinentes telles que les sous-requêtes, UNION et INTERSECT, et les expressions de table communes (CTE).

Partie 1 : Requêtes sur une seule table

Dans cette partie, nous allons récupérer et filtrer des données.

Remarque : pour écrire des requêtes correctes, vous devez d'abord vous familiariser avec les données stockées dans les tables.

Exercice 1 : Sélectionner les intitulés de poste de tous les employés masculins célibataires

Exercice : Sélectionnez le titre du poste de tous les employés masculins qui ne sont pas mariés.

Solution :

SELECT JobTitle
FROM HumanResources.Employee
WHERE Gender = 'M'
AND MaritalStatus != 'M';

Explication : Nous sélectionnons la colonne JobTitle du tableau. Employee de la table. Ici, la syntaxe SQL peut être lue exactement comme de l'anglais ordinaire.

Les conditions de filtrage sont placées dans la clause WHERE:

  • Nous voulons sélectionner uniquement les employés de sexe masculin, nous imposons donc une condition sur la colonne Gender: Gender = 'M'.
  • Nous voulons sélectionner uniquement les employés qui ne sont pas mariés, nous imposons donc une autre condition à la colonne MaritalStatus: MaritalStatus != 'M'.

Comme les deux conditions doivent s'appliquer en même temps, nous utilisons l'opérateur AND pour les combiner.

Exercice 2 : Sélectionner les employés dont le taux de rémunération est égal ou supérieur à 50

Exercice : Sélectionner les colonnes BusinessEntityID, Rate, et RateChangeDate pour tous les employés dont le taux de rémunération a déjà été de 50 ou plus.

Solution :

SELECT BusinessEntityID, Rate, RateChangeDate
FROM HumanResources.EmployeePayHistory
WHERE Rate >= 50;

Explication : Nous sélectionnons trois colonnes - BusinessEntityID, Rate, et RateChangeDate - dans le tableau. EmployeePayHistory tableau.

Nous ajoutons ensuite une condition de filtrage dans la clause WHERE pour ne récupérer que les employés dont le taux de rémunération a toujours été supérieur ou égal à 50 : Rate >= 50.

Exercice 3 : Sélectionner tous les employés qui ont rejoint de nouveaux départements en 2008

Exercice : Sélectionnez les adresses BusinessEntityID, DepartmentID, et StartDate pour chaque employé qui a commencé à travailler dans n'importe quel département en 2008.

Solution :

SELECT BusinessEntityID, DepartmentID, StartDate
FROM HumanResources.EmployeeDepartmentHistory
WHERE StartDate BETWEEN '2008-01-01' AND '2008-12-31';

Explication : Nous sélectionnons les ID des employés (BusinessEntityID), les ID des départements (DepartmentID) et la date à laquelle l'employé a rejoint ce département (StartDate) dans le tableau EmployeeDepartmentHistory table.

Comme nous voulons répertorier uniquement les employés qui ont rejoint de nouveaux départements en 2008, nous imposons une condition à la colonne StartDate: StartDate BETWEEN '2008-01-01' AND '2008-12-31'.

Cette condition est explicite, car elle est compréhensible en anglais. Nous voulons que la valeur de StartDate soit comprise entre le 1er janvier 2008 et le 31 décembre 2008, afin de couvrir tous les jours de l'année 2008.

Exercice 4 : sélectionner les départements dont les noms correspondent au modèle

Exercice : Sélectionnez les identifiants, les noms et les noms de groupe de tous les départements dont le nom commence par "Prod" OU de tous les départements dont le nom de groupe se termine par "ring".

Solution :

SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
WHERE Name LIKE 'Prod%'
OR GroupName LIKE '%ring';

Explication : Nous sélectionnons les colonnes DepartmentID, Name et GroupName dans le tableau. Department de la table.

Ensuite, nous indiquons les conditions de la clause WHERE:

  • Nous voulons sélectionner les départements dont le nom commence par "Prod", nous imposons donc une condition à la colonne Name: Name LIKE 'Prod%'.
  • Nous voulons également sélectionner les départements dont le nom de groupe se termine par "ring", nous imposons donc une condition sur la colonne GroupName: GroupName LIKE '%ring'.

Le mot-clé LIKE nous permet de définir le modèle auquel la valeur de la colonne doit correspondre. Par exemple, nous voulons que la colonne Name commence par "Prod", le motif est donc 'Prod%'; % pour toute séquence de caractères.

Comme nous voulons trouver tous les enregistrements pour lesquels au moins une des conditions est vraie, nous utilisons le mot-clé OR.

Exercice 5 : Sélectionner les départements qui appartiennent à certains groupes

Exercice : Sélectionner les noms des départements qui appartiennent soit au groupe "Recherche et développement", soit au groupe "Fabrication".

Solution :

SELECT Name
FROM HumanResources.Department
WHERE GroupName IN ('Research and Development', 'Manufacturing');

Explication : Nous sélectionnons la colonne Nom dans le Department de la table.

Comme nous voulons répertorier les départements qui appartiennent à des groupes définis, nous utilisons le mot-clé IN dans la condition de la clause WHERE: GroupName IN ('Research and Development', 'Manufacturing').

Cela permet de s'assurer que tous les départements appartenant aux groupes répertoriés dans le mot-clé IN sont affichés.

Partie 2 : Requêtes portant sur plusieurs tables

Dans cette partie, nous utiliserons JOINs pour combiner des données provenant de plusieurs tables.

Remarque : pour écrire des requêtes correctes, vous devez d'abord vous familiariser avec les données stockées dans les tables concernées.

Exercice 6 : Sélectionner des employés et leurs départements

Exercice : Sélectionner les ID des employés avec tous les noms des départements dans lesquels ils ont travaillé.

Solution :

SELECT edh.BusinessEntityID, d.Name
FROM HumanResources.EmployeeDepartmentHistory AS edh
JOIN HumanResources.Department AS d
ON edh.DepartmentID = d.DepartmentID;

Explication : Nous sélectionnons la colonne BusinessEntityID dans la table EmployeeDepartmentHistory et la colonne Name dans la table Department de la table.

Nous joignons ces deux tables en utilisant la clause JOIN sur leur colonne commune, DepartmentID.

Exercice 7 : sélectionner les titres de poste des employées et les dates de changement de service

Exercice : Sélectionnez l'ID de l'employé et l'intitulé du poste ainsi que les dates auxquelles l'employé a changé de département (StartDate) pour toutes les employées.

Solution :

SELECT e.BusinessEntityID, e.JobTitle, edh.StartDate
FROM HumanResources.Employee AS e
JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.BusinessEntityID = edh.BusinessEntityID
WHERE e.Gender = 'F';

Explication : Nous sélectionnons les colonnes BusinessEntityID et JobTitle dans le tableau et la colonne dans le tableau. Employee et la colonne StartDate de la table EmployeeDepartmentHistory de la table.

Nous utilisons la clause JOIN pour joindre les tables sur leur colonne commune, BusinessEntityID.

Comme nous voulons répertorier ces informations uniquement pour les employées, nous imposons une condition à la colonne Gender: e.Gender = 'F'.

Exercice 8 : Sélectionner les titres de postes par département

Exercice : Sélectionnez les titres de postes et les noms de départements correspondants pour trouver tous les titres de postes qui ont été utilisés dans chaque département. N'incluez pas les multiples d'un même titre de poste.

Solution :

SELECT DISTINCT e.JobTitle, d.Name
FROM HumanResources.Employee AS e
JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.BusinessEntityID = edh.BusinessEntityID
JOIN HumanResources.Department AS d
ON edh.DepartmentID = d.DepartmentID;

Explication : Nous sélectionnons la colonne JobTitle dans le tableau Employee et la colonne Name dans le tableau Department de la table.

Pour sélectionner des intitulés de poste distincts (c'est-à-dire sans doublons), nous utilisons le mot-clé DISTINCT avant le nom des colonnes.

Nous devons joindre la table Employee avec la table EmployeeDepartmentHistory sur leur colonne commune, BusinessEntityID. Ensuite, nous joignons la table EmployeeDepartmentHistoryavec la table Department sur leur colonne commune, DepartmentID.

Exercice 9 : Sélectionner les employés avec leurs départements et leurs équipes

Exercice : Sélectionnez des noms de service et des noms d'équipe distincts (pas de paires dupliquées) pour lesquels les employés de chaque service travaillent. Renommez le nom du service en DepartmentName et le nom de l'équipe en ShiftName.

Solution :

SELECT DISTINCT d.Name AS DepartmentName, s.Name AS ShiftName
FROM HumanResources.EmployeeDepartmentHistory AS edh
JOIN HumanResources.Department AS d
ON edh.DepartmentID = d.DepartmentID
JOIN HumanResources.Shift AS s
ON edh.ShiftID = s.ShiftID;

Explication : Nous sélectionnons la colonne Nom dans la table Department et la colonne Name dans la table Shift en leur attribuant des noms d'alias à l'aide du mot-clé AS. Nous utilisons DISTINCT pour sélectionner des paires distinctes.

Pour sélectionner les noms des départements et les noms des équipes, nous devons joindre ces trois tables :

  • Nous joignons la table EmployeeDepartmentHistory avec la table Department sur la table DepartmentID
  • Nous joignons la table EmployeeDepartmentHistory avec la table Shift sur la table ShiftID

Chacune des clauses JOIN a une clause ON qui définit les colonnes communes sur lesquelles la jointure est effectuée.

Exercice 10 : Sélectionner les employés embauchés après 2010 avec leurs départements et leurs équipes

Exercice : Sélectionnez les identifiants des employés, les noms des départements et les noms des équipes. Inclure seulement les employés embauchés après 2010-01-01 et qui travaillent pour les départements des groupes Fabrication et Assurance qualité.

Solution :

SELECT e.BusinessEntityID, d.Name, s.Name
FROM HumanResources.Employee AS e
JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.BusinessEntityID = edh.BusinessEntityID
JOIN HumanResources.Department AS d
ON edh.DepartmentID = d.DepartmentID
JOIN HumanResources.Shift AS s
ON edh.ShiftID = s.ShiftID
WHERE e.HireDate > '2010-01-01'
AND d.GroupName IN ('Manufacturing', 'Quality Assurance');

Explication : Nous sélectionnons la colonne BusinessEntityID dans le tableau Employees la colonne Name de la table Department et la colonne Name de la table Shift.

Pour sélectionner les identifiants des employés ainsi que les noms des services et des équipes, nous devons utiliser trois jointures :

  • Nous joignons la table Employee et la table EmployeeDepartmentHistory sur la colonne BusinessEntityID.
  • Nous joignons la table EmployeeDepartmentHistory avec la table Department sur la colonne DepartmentID
  • Nous joignons la table EmployeeDepartmentHistory avec la table Shift sur la colonne ShiftID.

Ensuite, nous fournissons les conditions de la clause WHERE comme suit :

  • Nous voulons lister tous les employés embauchés après le 1er janvier 2010, nous imposons donc une condition sur la colonne HireDate: HireDate > '2010-01-01'.
  • Nous voulons lister uniquement les employés qui appartiennent à certains groupes de départements, nous utilisons donc le mot-clé IN pour créer cette condition : GroupName IN ('Manufacturing', 'Quality Assurance').

Partie 3 : Regroupement et agrégation des données

Dans cette partie, nous allons regrouper et agréger des données afin de pouvoir effectuer des opérations mathématiques sur les données sélectionnées.

Note : Pour écrire des requêtes correctes, vous devez d'abord vous familiariser avec les données stockées dans les tables concernées.

Exercice 11 : Sélectionner les heures de congé de maladie les plus élevées et les plus basses

Exercice : Sélectionnez le nombre minimum et le nombre maximum d'heures de congé de maladie prises par les employés.

Solution :

SELECT MIN(SickLeaveHours) AS MinSickLeaveHours,
       MAX(SickLeaveHours) AS MaxSickLeaveHours
FROM HumanResources.Employee;

Explication : Nous utilisons les fonctions d'agrégation MIN() et MAX() - en fournissant la colonne SickLeaveHours du tableau comme argument - pour sélectionner les nombres minimum et maximum d'heures de congé de maladie prises par les employés. Employee comme argument - pour sélectionner les nombres minimum et maximum d'heures de congé maladie prises par les employés.

Exercice 12 : sélectionner le nombre moyen d'heures de vacances par fonction

Exercice : Sélectionnez les intitulés de poste et le nombre moyen d'heures de vacances par intitulé de poste.

Solution :

SELECT JobTitle, AVG(VacationHours) AS AvgVacationHours
FROM HumanResources.Employee
GROUP BY JobTitle;

Explication : Nous sélectionnons la colonne JobTitle du tableau. Employee tableau.

Nous utilisons la fonction d'agrégation AVG() pour obtenir le nombre moyen d'heures de congé pour chaque poste. Nous voulons avoir des groupes de données basés sur les valeurs distinctes de la colonne JobTitle; cela nécessite l'utilisation de la clause GROUP BY avec la colonne JobTitle comme argument.

Exercice 13 : Sélectionner le nombre d'employés en fonction de leur sexe

Exercice : Sélectionner le sexe des employés et le nombre d'employés de chaque sexe.

Solution :

SELECT Gender, COUNT(*) AS Count
FROM HumanResources.Employee
GROUP BY Gender;

Explication : Nous sélectionnons la colonne Gender dans le Employee tableau.

Nous utilisons la fonction d'agrégation COUNT() pour obtenir le nombre d'employés pour chaque sexe. Pour ce faire, nous devons utiliser la clause GROUP BY avec la colonne Gender comme argument ; nous voulons avoir des groupes de données basés sur les valeurs distinctes de la colonne Gender.

Exercice 14 : Sélectionner le nombre de départements dans chaque groupe

Exercice : Trouvez le nombre de départements dans chaque groupe de départements. N'indiquez que les noms des groupes de départements qui ont plus de deux départements.

Solution :

SELECT GroupName, COUNT(*) AS DepartmentsCount
FROM HumanResources.Department
GROUP BY GroupName
HAVING COUNT(*) > 2;

Explication : Nous sélectionnons la colonne GroupName dans la table Département.

Nous utilisons la fonction d'agrégation COUNT() pour obtenir le nombre de départements dans chaque groupe de départements. Pour ce faire, nous devons utiliser la clause GROUP BY avec la colonne GroupName comme argument.

Pour imposer une condition à la fonction d'agrégation, nous utilisons la clause HAVING après la clause GROUP BY: HAVING COUNT(*) > 2.

Exercice 15 : Sélectionner la somme des heures de congés maladie pour chaque département

Exercice : Sélectionnez les noms des départements et la somme des heures de congé de maladie prises par les employés travaillant actuellement dans chaque département. Renommez cette colonne en SumSickLeaveHours.

Solution :

SELECT d.Name, SUM(e.SickLeaveHours) AS SumSickLeaveHours
FROM HumanResources.Employee AS e
JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.BusinessEntityID = edh.BusinessEntityID
JOIN HumanResources.Department AS d
ON edh.DepartmentID = d.DepartmentID
WHERE edh.EndDate IS NULL
GROUP BY d.Name;

Explication : Nous sélectionnons la colonne Nom dans la colonne Department.

Nous utilisons la fonction d'agrégation SUM() pour obtenir la somme des heures de congé de maladie utilisées par les employés de chaque service. Pour ce faire, nous devons utiliser la clause GROUP BY avec la colonne Nom de la table Department comme argument.

Nous devons joindre la table Employee avec la table EmployeeDepartmentHistory sur la colonne BusinessEntityID. Ensuite, nous joignons la table EmployeeDepartmentHistoryavec la table Department sur la colonne DepartmentID.

Comme nous ne considérons que les employés qui travaillent actuellement dans un département, nous imposons une condition selon laquelle la colonne EndDate de la table EmployeeDepartmentHistory doit être NULL.

Partie 4 : Autres fonctions SQL

Dans cette partie, nous aborderons les sous-requêtes (c'est-à-dire les requêtes imbriquées les unes dans les autres), les opérateurs tels que UNION et INTERSECT, et les expressions de table communes (CTE).

Remarque : pour écrire des requêtes correctes, vous devez d'abord vous familiariser avec les données stockées dans les tables concernées.

Exercice 16 : Sélectionner les employés avec leur taux de rémunération actuel

Exercice : Sélectionner les identifiants des employés et leurs taux de rémunération actuels.

Solution :

SELECT e.BusinessEntityID, e.Rate AS CurrentPayRate
FROM HumanResources.EmployeePayHistory AS e
WHERE e.RateChangeDate = (
			SELECT MAX(e2.RateChangeDate)
			FROM HumanResources.EmployeePayHistory AS e2
			WHERE e2.BusinessEntityID = e.BusinessEntityID
		);

Explication : Nous sélectionnons les colonnes BusinessEntityID et Rate de la table. EmployeePayHistory table.

Étant donné que la table EmployeePayHistory stocke l'historique des taux de rémunération de chaque employé, nous devons imposer une condition pour que la valeur de la colonne RateChangeDate soit égale à la date la plus récente de modification du taux de rémunération d'un employé. Pour ce faire, nous définissons une sous-requête dans la clause WHERE qui sélectionne la date la plus récente à laquelle le taux de rémunération a été modifié. Cette sous-requête utilise la fonction d'agrégation MAX() pour sélectionner la date la plus récente.

Nous sélectionnons la date la plus récente RateChangeDate pour chaque employé séparément, nous ajoutons donc une clause WHERE dans la sous-requête pour faire correspondre les ID des employés entre les requêtes externe et interne.

Exercice 17 : sélectionner les taux de rémunération minimum, moyen et maximum

Exercice : Sélectionner les taux de salaire minimum, moyen et maximum à partir des taux de salaire actuels des employés.

Solution :

SELECT MIN(CurrentPayRate) AS MinPayRate,
       AVG(CurrentPayRate) AS AvgPayRate,
       MAX(CurrentPayRate) AS MaxPayRate
FROM (
		SELECT e.BusinessEntityID, e.Rate AS CurrentPayRate
		FROM HumanResources.EmployeePayHistory AS e
		WHERE e.RateChangeDate = (
				SELECT MAX(e2.RateChangeDate)
				FROM HumanResources.EmployeePayHistory AS e2
				WHERE e2.BusinessEntityID = e.BusinessEntityID
			)
) AS cpr;

Explication : Nous utilisons les fonctions agrégées MIN(), AVG() et MAX() pour sélectionner les taux de salaire minimum, moyen et maximum, en fournissant la colonne CurrentPayRate de la sous-requête comme argument.

Nous utilisons la sous-requête dans la clause FROM. Cette sous-requête sélectionne les taux de rémunération actuels pour chaque employé, comme expliqué dans l'exercice 16.

Notez que cette solution imbrique deux sous-requêtes. Tout d'abord, nous utilisons une sous-requête dans la clause FROM. Ensuite, cette sous-requête utilise une sous-requête dans sa propre clause WHERE.

Exercice 18 : sélection des ID des employés avec leurs heures d'absence du bureau

Exercice : Sélectionner tous les identifiants des employés qui ont pris plus de 60 heures de vacances ou qui ont pris plus de 60 heures de congés maladie.

Solution :

SELECT BusinessEntityID
FROM HumanResources.Employee
GROUP BY BusinessEntityID
HAVING SUM(VacationHours) > 60

UNION

SELECT BusinessEntityID
FROM HumanResources.Employee
GROUP BY BusinessEntityID
HAVING SUM(SickLeaveHours) > 60;

Explication : La première requête sélectionne la colonne BusinessEntityID dans la table Employee et utilise la fonction d'agrégation SUM() pour additionner le nombre d'heures de vacances prises par chaque employé. Nous regroupons les données en fonction de l'ID de l'employé et imposons une condition selon laquelle la somme doit être supérieure à 60.

De la même manière, la deuxième requête sélectionne la colonne BusinessEntityID dans la table et utilise la fonction d'agrégation pour additionner le nombre d'heures de vacances prises par chaque employé. Employee et utilise la fonction d'agrégation SUM() pour additionner le nombre d'heures de congé maladie prises par chaque employé. Nous regroupons les données en fonction de l'ID de l'employé et imposons une condition selon laquelle la somme doit être supérieure à 60.

L'opérateur UNION combine les résultats des deux requêtes.

Exercice 19 : sélection des ID d'employés avec certains titres de poste et départements

Exercice : Sélectionnez les ID des employés qui ont les titres de poste "Représentant des ventes" ou "Concepteur d'outils" et qui ont travaillé (ou travaillent) dans les départements "Ventes" ou "Marketing".

Solution :

SELECT e.BusinessEntityID
FROM HumanResources.Employee AS e
WHERE e.JobTitle IN ('Sales Representative', 'Tool Designer')

INTERSECT

SELECT edh.BusinessEntityID
FROM HumanResources.EmployeeDepartmentHistory AS edh
JOIN HumanResources.Department AS d
ON edh.DepartmentID = d.DepartmentID
WHERE d.Name IN ('Sales', 'Marketing');

Explication : La première requête sélectionne la colonne BusinessEntityID dans la table Employee de la table. Elle filtre la colonne JobTitle pour n'inclure que les représentants commerciaux et les concepteurs d'outils.

La deuxième requête sélectionne la colonne BusinessEntityID dans la table. EmployeeDepartmentHistory de la table. Elle filtre le nom du département pour n'inclure que les départements des ventes et du marketing.

L'opérateur INTERSECT trouve la sortie commune des deux requêtes - c'est-à-dire qu'il ne produira que les ID des employés qui remplissent les conditions de la clause WHERE des deux requêtes.

Exercice 20 : lister les représentants des ventes et les responsables marketing avec leurs départements

Exercice : Sélectionnez les ID, les titres de poste et les noms de service des employés associés aux rôles de représentant des ventes ou de responsable marketing.

Solution :

SELECT e.BusinessEntityID, e.JobTitle, d.Name AS DepartmentName
FROM HumanResources.Employee AS e
JOIN HumanResources.EmployeeDepartmentHistory AS edh 
ON e.BusinessEntityID = edh.BusinessEntityID
JOIN HumanResources.Department AS d
ON edh.DepartmentID = d.DepartmentID
WHERE e.JobTitle IN ('Sales Representative', 'Marketing Manager');

Explication : La requête utilise un JOIN pour relier la table Employee avec la table EmployeeDepartmentHistory sur la base de la colonne BusinessEntityID. Cette jointure garantit que l'enregistrement de chaque employé est lié à l'historique de son département.

Un autre JOIN relie la table EmployeeDepartmentHistory à la table Department à l'aide de la clause DepartmentID, ce qui permet à la requête d'extraire les informations sur le département liées à l'historique de l'emploi de l'employé.

La clause WHERE filtre les résultats pour n'inclure que les employés dont le titre de poste est soit "Représentant des ventes", soit "Responsable marketing". Ce filtrage est effectué à l'aide de l'opérateur IN, qui spécifie les intitulés de poste souhaités. La structure de la requête combine et filtre efficacement les données provenant de plusieurs tables afin de renvoyer les titres de poste des employés et les départements associés.

Pratiquez le langage SQL avec les exercices d'AdventureWorks !

Dans cet article, vous avez exploré les principes fondamentaux du langage SQL en utilisant des exercices avec la base de données AdventureWorks. Vous avez appris à effectuer des requêtes sur une seule table avec SELECT, à combiner des données de table avec JOIN, à grouper des données avec GROUP BY, et à utiliser des fonctions d'agrégation comme COUNT(), AVG(), SUM(), MIN() et MAX(). En outre, vous avez étudié les sous-requêtes, UNION et INTERSECT.

Pour plus d'exercices avec solutions et explications détaillées, consultez nos articles 10 exercices pour débutants La pratique du SQL avec solutions et SQL Joins : 12 questions pratiques avec réponses détaillées. Plongez plus profondément dans les opportunités de pratique SQL avec notre guide complet de La pratique du SQL sur LearnSQL.com. Et comme je l'ai mentionné plus tôt, vous pouvez également continuer votre pratique avec notre piste La pratique du SQL , les bases de données de pratique SQL, ou le cours mensuel gratuit de SQL.

Bonne chance dans votre périple SQL !