Aller au contenu

Niveau physique : le langage SQL

Présentation du langage SQL

Qu'est-ce que c'est ?

  • Ce niveau concerne l'implantation et l'utilisation de la base de données.

  • C'est le langage SQL qui va permettre cela.

Définition : langage SQL

  • Langage informatique standardisé, implémenté sur la plupart des SGBD relationnels principaux (Oracle, Access, MySQL, etc.) ;
  • Il se décompose en 3 sous-langages, pour :
    • la définition des données (LDD) ;
    • leur manipulation (LMD)
    • leur contrôle d'accès (LCD).
  • SQL a été conçue en vue d’une intégration multi-langage (C, C++, Java, PHP, Python, etc.).
  • C'est un langage déclaratif et non procédural.
  • Le langage SQL décrit est 100% compatible avec MySQL.

Bref historique

  • Provient du langage System R d’IBM (1976).
  • Apparaît pour la première fois dans une application commerciale avec Oracle (fin 1970).
  • 1ère normalisation ANSI : SQL-86.
  • Normalisations ultérieures : SQL-89, SQL-92, SQL-99, SQL-1999, SQL-2003, SQL-2008.
  • Norme actuelle : SQL-2011.

Le LDD : Langage de Définition de Données

Les types de données

Définition : type (de données) d'un champ

Dans une déclaration de table - en SQL - il est nécessaire d'affecter un type à chaque champ (ou colonne). Ce type détermine le domaine du champ, c'est-à-dire l'ensemble des valeurs qu'il peut prendre dans les différents enregistrements.

Les nombres entiers

  • BIGINT[(x)] : 8 octets (x désigne le nombre maximal de chiffres dans l'affichage)
  • INTEGER[(x)] ou INT[(x)] : 4 octets
    x = nombre minimal de chiffres affichés, si ZEROFILL
  • MEDIUMINT[(x)] : 3 octets
  • SMALLINT[(x)] : 2 octets
  • TINYINT[(x)] : 1 octet
  • BIT, BOOL, BOOLEAN = TINYINT(1)

Leur déclaration peut être suivie de :
- [UNSIGNED]
- [ZEROFILL] : complétion du nombre par des 0 dans l'affichage ; implique UNSIGNED.

Les nombres réels

  • Ils supportent : [UNSIGNED] et [ZEROFILL].
Types approchés
  • FLOAT[(n,d)] : 4 octets (entre parenthèses, le nombre de chiffres à afficher : après et avant la virgule)
  • DOUBLE [(n,d)] = REAL[(n,d)] : 8 octets
Types exacts
  • DECIMAL[(n,d)] = NUMERIC[(n,d)]

  • nombre stocké comme une chaîne de caractères

  • 1 caractère par chiffre

Les chaînes de caractères

Champs texte courts
  • CHAR(n) [BINARY] : chaîne de longueur fixe, occupant n caractères
  • VARCHAR(n) [BINARY] : chaîne de longueur variable, occupant au plus n caractères

  • BINARY : les comparaisons tiennent compte de la casse

Champs texte longs
  • Chaînes de caractères insensibles à la casse

    • TINYTEXT : 2^8 (– 1) caractères
    • TEXT : 2^16 caractères
    • MEDIUMTEXT : 2^24 caractères
    • LONGTEXT : 2^32 caractères
  • Chaînes sensibles à la casse

    • TINYBLOB
    • BLOB
    • MEDIUMBLOB
    • LONGBLOB

Les dates et temps

  • DATE : AAAA-MM-JJ : jour entre 1/1/1000 et 12/31/9999
  • YEAR : AAAA
  • TIME : HH:MM:SS (format 24h)

  • TIMESTAMP : jour entre 1/1/1970 et 19/1/2038

    • si valeur non précisée, par défaut c’est la date courante
  • DATETIME : AAAA-MM-JJ HH:MM:SS (date et heure)

  • DATETIME et TIMESTAMP sont stockés suivant l'échelle de temps UTC.

Les valeurs manquantes : NULL

Définition : « valeur » NULL

Un champ d'enregistrement peut (sauf si affecté par la propriété NOT NULL) prendre la « valeur particulière » NULL : elle désigne une valeur manquante. Cela n'est donc pas vraiment une valeur, simplement un code en spécifiant l'absence.

Création de la base et des tables

Création d’une base

        CREATE DATABASE <nom_base>;

Définition de la « base de travail »

Pour créer des tables au sein d'une base, on peut éviter de mentionner leur appartenance à cette base, en la définissant comme « base de travail » :

        USE <nom_base>;

Création d'une table

  • Dans MySQL, chaque table est stockée dans un fichier
  • Syntaxe simplifiée :
        CREATE [TEMPORARY] TABLE [IF NOT EXISTS] <nom_table>
        (
            <nom_colonne1> <type> [<propriété>]*,
            <nom_colonne2> <type> [<propriété>]*,
            
            <nom_colonne1> <type> [<propriété>]*,
            [<contraintes_de_table>]
        );
  • TEMPORARY : permet la création d'une table dont la durée d'existence est limitée à la session courante.
Propriétés des colonnes de la table
  • Initialisation

    • AUTO_INCREMENT : uniquement pour les types numériques
    • DEFAULT <valeur par défaut> : sauf pour les textes longs
  • Contraintes d'intégrité : certaines de ces propriétés instaurent des vérifications automatiques qui garantissent la cohérence de la base

    • NOT NULL (et NULL par défaut) : autorise ou non les NULL
    • UNIQUE(si aussi NOT NULL alors colonne = clé candidate)
    • PRIMARY KEY (définit clé primaire) (= NOT NULL + UNIQUE)
    • CHECK(<condition>)
Propriétés de table = contraintes d’intégrité sur une table
  • PRIMARY KEY(<liste_de_champs>)
  • UNIQUE(<liste_de_champs>)
  • (INDEX = KEY)
  • + gestion des clés étrangères

  • ENGINE : format de stockage de la base.

    • Valeur INNODB par défaut : permet les transactions sécurisées et la gestion des clés étrangères
Gestion des clés étrangères
  • Syntaxe simplifiée :
        FOREIGN KEY [nom_contrainte] (<liste_colonnes>) 
            REFERENCES <table> (<liste_colonnes>)
            [ON DELETE CASCADE|SET NULL|NO ACTION|RESTRICT]
            [ON UPDATE CASCADE|SET NULL|NO ACTION|RESTRICT]
  • La clé étrangère établit un lien entre une table parente (celle « référencée ») et une table fille (celle qui référence des enregistrements de la table parente)

    • La déclaration se fait dans la table parente.
    • Les champs mis en relations doivent être de même type (avec des propriétés compatibles).
    • Pour des raisons d'efficacité, il faut obligatoirement des index sur les clés étrangères et leurs références (pas nécessairement des clés primaires). Mais les déclarations de clés suffisent à les créer.
  • RESTRICT = NO ACTION (pour MySQL) : rejet de l'effacement ou de la modification.

Exemple de définition d'une table, avec une contrainte de clé étrangère

        DROP TABLE IF EXISTS Magasin;
        CREATE TABLE Magasin
        (
            n_mag TINYINT(3) UNSIGNED NOT NULL AUTO_INCREMENT,
            nom VARCHAR(100) NOT NULL,
            adresse VARCHAR(100) NOT NULL,
            tel VARCHAR(10),
            code_postal MEDIUMINT(5) ZEROFILL NOT NULL,
            PRIMARY KEY(n_mag),
            INDEX Poste_Code_postal (code_postal), -- facultatif et peut être intégré à la commande suivante
            FOREIGN KEY (code_postal) REFERENCES Poste(code_postal) ON UPDATE CASCADE ON DELETE CASCADE
        ) TYPE = InnoDB;

Modification (du schéma des) tables

  • Suppression
            DROP TABLE [IF EXISTS] <nom_table1>, , <nom_tableN>
  • Modification
                ALTER TABLE <nom_table> <alteration>
    
    • Altérations possibles

      • Type de colonne
                    MODIFY <nom_colonne> <nouvelle_definition_colonne>
        
      • Nom et type de colonne
                    CHANGE <ancien_nom_colonne> <nouveau_nom_colonne> <nouvelle_definition_colonne>
        
      • Ajout d’une colonne
                    ADD <nom_col> <def_col> [FIRST|AFTER <nom_col>]
        
      • Suppression d’une colonne
                    DROP <nom_col>
        
      • Renommage de la table
                    RENAME AS <nouveau_nom_table>
        
      • Suppression ou ajout d’une valeur par défaut
                    ALTER <nom_col> {SET DEFAULT <valeur> |DROP DEFAULT}
        
      • Suppression ou ajout de contraintes d’intégrité
                    DROP PRIMARY KEY
                    ADD CONSTRAINT {PRIMARY KEY|UNIQUE} <liste_colonnes>
        

Le LMD : Langage de Manipulation de Données

Les premières requêtes

Définition : requête SQL

Une requête sert à extraire des données de la base, à partir d'une ou plusieurs tables. On les exprime à l'aide de l'instruction SELECT.

L'instruction SELECT

L'instruction SELECT permet de construire une pseudo-table résultat (table sans nom, non persistante), à partir d'une ou plusieurs tables.

Voici sa syntaxe simplifiée :

    SELECT [DISTINCT] <champ1>, <champ2>, 
    FROM <table1>, <table2>, 
    WHERE <conditions>

Une première requête : la liste complète des étudiants

    SELECT Prenom, Nom, NumeroINE
    FROM Etudiant

Pour comprendre le processus de construction de la requête, il est préférable de considérer (et rédiger) ses différentes clauses dans l'ordre, à l'exception du SELECT dont l'action n'intervient qu'à la toute fin :

  1. La clause FROM cible la table de travail, à partir de laquelle la pseudo-table résultat va être construite. Lorsque plusieurs tables sont listées, c'est leur produit cartésien qui servira de (pseudo-)table de travail (voir plus loin).

  2. La clause WHERE sert à filtrer les enregistrements (c.-à-d. les lignes) de la table de travail : seules celles vérifiant les conditions requises sont conservées.

  3. La clause SELECT elle-même permet de sélectionner les champs (c.-à-d. les colonnes) de la table de travail : seuls ceux listés seront conservés.

    • C'est la seule clause véritablement obligatoire de la requête.
    • Comme son nom ne l'indique pas, il s'agit plutôt d'une clause de « projection » : sélectionner les champs revient en effet à réduire la « dimension » des enregistrements de la table résultat.
    • Le champ optionnel DISTINCT permet d'éliminer les doublons parmi les enregistrements du résultat.

La clause WHERE : sélection/restriction des enregistrements

La restriction des enregistrements de la table de travail s'effectue à l'aide de conditions sur leur contenu, à l'aide de différents opérateurs :

  • Les opérateurs de comparaison : =, !=, <, >, <=, >=.

  • Les prédicats (« opérateurs intégrés » ) : BETWEEN, IN, LIKE, IS NULL

    • BETWEEN vérifie qu'un champ appartient à un intervalle donné :

      Exemple : liste des étudiants associés aux 10 premiers stages

          SELECT *
          FROM Etudiant
          WHERE NumeroStage BETWEEN 1 AND 10
      
    • IN vérifie l'appartenance à un ensemble de valeurs :

      Exemple : liste des étudiants effectuant les stages 1, 12 ou 18

          SELECT *
          FROM Etudiant
          WHERE NumeroStage IN (1,12,18)
      
    • LIKE vérifie qu'une donnée de type « chaîne de caractères » correspond à un modèle de chaîne. Un modèle s'élabore à partir d'une chaîne de caractères constante, dans laquelle les éventuels symboles spéciaux _ et % représentent respectivement un caractère quelconque et une suite quelconque de caractères.

      Exemple : liste des étudiants dont le nom se termine par un « d » et dont la 2ième lettre est un « a »

          SELECT *
          FROM Etudiant
          WHERE Nom LIKE "_a%d"
      
    • IS NULL et IS NOT NULL vérifient qu'un champ est manquant ou non :

      Exemple : liste des étudiants sans stage

          SELECT Prenom, Nom, NumeroINE
          FROM Etudiant
          WHERE NumeroStage IS NULL
      
  • Enfin, les opérateurs logiques permettent de combiner les conditions, AND et OR, ou de les inverser, avec NOT.

La clause WHERE et les sous-requêtes

Définition : sous-requête

  • Dans la condition de sélection/restriction des enregistrements (clause WHERE), les données manipulées peuvent être obtenues par une requête complète (SELECT FROM WHERE).
  • Cette requête utilisée par la requête principale est appelée sous-requête.

Sous-requêtes basées sur l'opérateur IN

  • Sous-requête et opérateur IN :

Exemple : noms et prénoms des stagiaires de M. Bellamy

    SELECT Prenom, Nom
    FROM Etudiant
    WHERE NumeroStage IN (
        SELECT NumeroStage
        FROM Stage
        WHERE Encadrant = "Bellamy"
    )
  • Plusieurs requêtes imbriquées :

Exemple : noms et prénoms des stagiaires des encadrants dont le nom commence par un « D ».

    SELECT Prenom, Nom
    FROM Etudiant
    WHERE NumeroStage IN (
        SELECT NumeroStage
        FROM Stage
        WHERE Encadrant IN (
            SELECT Encadrant
            FROM Stage
            WHERE Encadrant LIKE "D%"
        )
    )
  • Comme dans la plupart des langages informatiques, les requêtes imbriquées ont accès aux champs des requêtes qui les englobent ; mais pas l'inverse.

Exemple : noms et prénoms des étudiants dont l'encadrant porte le même nom

    SELECT Prenom, Nom
    FROM Etudiant
    WHERE NumeroStage IN (
        SELECT NumeroStage
        FROM Stage
        WHERE Encadrant = Etudiant.Nom
    )

Sous-requêtes basées sur d'autres opérateurs

  • Si une sous-requête renvoie une seule valeur, on peut utiliser les autres opérateurs de comparaison :

Exemple : numéros des stages encadrés par l'encadrant du stage 7

    SELECT NumeroStage
    FROM Stage
    WHERE Encadrant = (
        SELECT Encadrant
        FROM Stage
        WHERE NumeroStage = 7 
    )
  • La sous-requête peut renvoyer le résultat d'une fonction d'agrégation (voir plus loin), comme un comptage. Dans cet exemple, notez que la même table est utilisée dans la requête et la sous-requête : on utilise alors des alias pour lever les ambiguïtés sur les tables.

Exemple : liste des encadrants ayant au moins de 2 stages

    SELECT DISTINCT Encadrant
    FROM Stage AS Stage_requete
    WHERE 2 <= (
        SELECT COUNT(*) -- comptage des lignes
        FROM Stage AS Stage_sous_requete
        WHERE Stage_sous_requete.Encadrant = Stage_requete.Encadrant
    )
  • Les opérateurs ensemblistes EXISTS et NOT EXISTS

Exemple : intitulés des stages affectés à plus d'un stagiaire

    SELECT DISTINCT Titre
    FROM Stage as Table_parent
    WHERE EXISTS (
        SELECT *
        FROM Stage 
        WHERE NumeroStage != Table_parent.NumeroStage AND Titre = Table_parent.Titre
    )
  • Application des opérateurs de comparaisons à des listes de valeurs, à l'aide de ALL et ANY

Exemple : prénom et nom de l'étudiant qui a le plus petit numéro de stage parmi ceux les stages affectés (il existe d'autres méthodes plus adaptées !)

    SELECT Prenom, Nom
    FROM Etudiant
    WHERE NumeroStage <= ALL (
        SELECT NumeroStage
        FROM Etudiant
        WHERE NumeroStage IS NOT NULL
    )

Exemple : prénoms et noms des étudiants qui n'ont pas le plus petit numéro de stage parmi les stages affectés

    SELECT Prenom, Nom
    FROM Etudiant
    WHERE NumeroStage > ANY (
        SELECT NumeroStage
        FROM Etudiant 
        WHERE NumeroStage IS NOT NULL
    )

La clause FROM et les requêtes multi-tables

Le produit cartésien

Définition : produit cartésien

  • Mathématiquement, le produit cartésien de 2 ensembles est l'ensemble de tous les couples constitués d'un élément du 1er ensemble, et d'un élément du 2nd ensemble.
    • Par exemple, RxR est l'ensemble des points du plan (R désignant l'ensemble des réels).
  • Pour appliquer ce produit en BDD, il suffit de considérer qu'une table est un ensemble d'enregistrements.
  • Le produit cartésien de 2 tables est donc une table dont les enregistrements sont définis en combinant (ou couplant) chaque enregistrement de la 1ère table avec chaque enregistrement de la 2nde.

    • Combiner 2 enregistrements consiste à compléter le 1er par le 2nd (par concaténation de leurs champs).
    • Le schéma de la table résultat est donc constitué de la réunion des champs des 2 tables.
  • Le produit cartésien de n>2 tables s'obtient en calculant le produit cartésien de la première table, avec le produit cartésien des autres tables.

Exemple de produit cartésien mathématique : liste de tous les devoirs d'élèves

Ensemble 1Élèves = {"Marie", "Alfred", "Blaise"}
Ensemble 2Devoirs = {"Commentaire de texte", "Dissertation"}

Produit cartésien des ensembles 1 et 2 :

Élèves x Devoirs = {
        ("Marie", "Commentaire de texte"),
        ("Marie", "Dissertation"),
        ("Alfred", "Commentaire de texte"),
        ("Alfred", "Dissertation"),
        ("Blaise", "Commentaire de texte"),
        ("Blaise", "Dissertation")
}

Exemple de produit cartésien BDD : liste de tous les devoirs d'élèves

On réalise le produit cartésien entre les 2 tables suivantes :

Table Élèves

Nom Prenom
Curie Marie
Einstein Alfred
Pascal Blaise

Table Devoirs

Libellé Matière
Commentaire de texte Français
Dissertation Français

Résultat du produit cartésien des 2 tables, noté : Élèves x Devoirs

    --- instruction SQL qui calcule ce produit cartésien
    SELECT *
    FROM Eleves, Devoirs

Élèves.Nom Élèves.Prénom Devoirs.Libellé Devoirs.Matière
Curie Marie Commentaire de texte Français
Curie Marie Dissertation Français
Einstein Alfred Commentaire de texte Français
Einstein Alfred Dissertation Français
Pascal Blaise Commentaire de texte Français
Pascal Blaise Dissertation Français

La jointure

Définition : jointure

  • Formellement, une jointure est une restriction de produit cartésien. Cela signifie que contrairement à ce dernier, elle ne conserve pas toutes les combinaisons d'enregistrements, mais uniquement celles qui vérifient une condition de jointure.
  • En BDD, on l'utilise fréquemment pour compléter les enregistrements contenant une clé étrangère, par l'enregistrement - de la table liée - dont la clé primaire lui correspond.
    • Elle permet alors de recomposer des données dont le contenu a été réparti entre plusieurs tables dans l'étape de conception (la conception visant à minimiser la redondance des données de la base).

Exemple de jointure : liste des étudiants avec les informations de leur stage

    SELECT NumeroINE, Prenom, Nom, Stage.Titre, Stage.Encadrant
    FROM Etudiant JOIN Stage ON (Etudiant.NumeroStage = Stage.NumeroStage)

En considérant la jointure comme une restriction de produit cartésien, on peut aussi écrire :

    SELECT NumeroINE, Prenom, Nom, Stage.Titre, Stage.Encadrant
    FROM Etudiant, Stage
    WHERE Etudiant.NumeroStage = Stage.NumeroStage

Sans la clause de jointure Etudiant.NumeroStage = Stage.NumeroStage, chaque étudiant serait combiné à chacun des stages : cela n'aurait aucun sens !

Définitions : jointures internes et externes

    • elles contiennent exclusivement les combinaisons d'enregistrements associés par la condition de jointure : les enregistrements orphelins des 2 tables initiales (c.-à-d. « non associés ») sont ainsi exclus du résultat.
    • c'est la jointure par défaut : le mot clé INNER est implicitement associé à JOIN lorsqu'il est seul.

    Les jointures internes (INNER JOIN)

    Exemple de jointure interne : ni les étudiants sans stage, ni les stages sans étudiants, n'apparaissent dans le résultat

        SELECT NumeroINE, Prenom, Nom, Stage.Titre, Stage.Encadrant
        FROM Etudiant JOIN Stage ON Etudiant.NumeroStage = Stage.NumeroStage
    
  • Les jointures externes (OUTER JOIN)

    • plus complètes que les jointures internes, elles lui ajoutent les enregistrement orphelins (c.-à-d. « non associés ») de l'une ou l'autre des relations, voire des deux.
    • jointure gauche (LEFT [OUTER] JOIN) : jointure interne augmentée des enregistrements orphelins de la première table (ou encore : ensemble des enregistrements de la première table, complétés - si possible - par les enregistrements de la seconde).
    • jointure droite (RIGHT [OUTER] JOIN) : jointure interne augmentée des enregistrements orphelins de la seconde table.
    • jointure complète (FULL [OUTER] JOIN) : jointure interne augmentée de tous les enregistrements orphelins (de la première et de la seconde table).
      • Attention, elle n'existe pas dans MySQl.

    Exemple de jointure externe droite : liste des stages non affectés

        SELECT Stage.* 
        FROM Etudiant RIGHT JOIN Stage ON Etudiant.NumeroStage = Stage.NumeroStage
        WHERE NumeroINE IS NULL
    
    • Le schéma des jointures est défini comme la réunion des champs des 2 tables. Logiquement, les enregistrements supplémentaires de la jointure externe (ceux orphelins) ne sont caractérisés que par les champs d'une des 2 tables : les champs provenant de l'autre table sont automatiquement fixés à NULL.

Définition : jointure naturelle

Une jointure naturelle (NATURAL JOIN) est une jointures sans condition de jointure explicite : une condition d'égalité est implicitement imposée entre tous les champs communs aux 2 tables jointes.

  • Elle n'a donc pas de clause ON.
  • Elle peut être interne comme externe.

Exemple de jointure naturelle (interne) : le seul champ commun aux tables Etudiant et Stage étant NumeroStage, l'exemple précédent se simplifie ainsi

        SELECT NumeroINE, Prenom, Nom, Stage.Titre, Stage.Encadrant
        FROM Etudiant NATURAL JOIN Stage

Les fonctions d'agrégation et groupements

Les fonctions d'agrégation

Définition : agréger, agrégat

  • Pour le Larousse, agréger c'est : « réunir en un tout des parties distinctes ».
  • L'agrégat désigne alors le résultat de cette opération : le « tout » obtenu.

Définition : fonction d'agrégation

Une fonction d'agrégation calcule une statistique sur un ensemble (un agrégat) d'enregistrements.

  • En « stats », on appelle « statistique » une fonction d'un échantillon de valeurs, qui lui associe généralement une valeur réelle. C'est un indicateur synthétique, au sens où il caractérise la structure de l'échantillon, de manière condensée. Par exemple, le minimum (la plus petite valeur de l'échantillon), la moyenne (la valeur « centrale » de l'échantillon), l'écart-type (la « dispersion »), etc.
  • Quelques fonctions d'agrégation SQL, qui s'appliquent généralement à une expression <expr> (un calcul effectué sur chaque enregistrement, de type nombre, date ou chaîne de caractères) :
    • MIN(<expr>), MAX(<expr>) : minimum et maximum du champ ;
    • SUM([DISTINCT] <expr>) : somme du champ (qui doit être de type numérique) ;
    • COUNT([DISTINCT] <expr>) : nombre d'enregistrements dans lequel le champ est non NULL;
    • COUNT(*) : nombre total d'enregistrements de l'agrégat ;
    • AVG([DISTINCT] <expr>) : moyenne.
    • VARIANCE(<expr>) : variance.
  • Les fonctions d'agégation se placent dans la clause SELECT.
  • L'ensemble d'enregistrements agrégé par défaut est la table résultat, toute entière.
  • Sitôt qu'une fonction d'agrégation est projetée par le SELECT, l'ensemble d'enregistrements sur lequel elle opère disparaît de la table résultat : il est remplacé par un unique enregistrement « synthétique » (qui caractérise la globalité de ces enregistrements : l'agrégat).

Exemple de fonction d'agrégation : proportion d'étudiants sans stage

        SELECT ( COUNT(*) - COUNT(NumeroStage) )/COUNT(*)
        FROM Etudiant

Les groupements

Définition : groupement

  • Les fonctions d'agrégation s'appliquent par défaut à la totalité des enregistrements. Un groupement permet de les agréger en ensembles plus petits.
  • Les groupes (ou agrégats) sont constitués d'enregistrements ayant certains « points en commun ».
    • En pratique, on propose une série d'expressions, et les enregistrements sont regroupés par égalité de valeurs sur toutes ces expressions.
    • C'est la clause GROUP BY qui permet de les introduire.
    • Lorsqu'une expression n'est pas définie pour certains enregistrements (NULL), alors ces enregistrements s'agrègent ensemble. Autrement dit, NULL se comporte comme une valeur.
  • La clause SELECT se compose uniquement :
    • d'expressions (dont colonnes) mentionnées dans le GROUP BY ;
    • de fonctions d'agégration.

Exemple de groupement : nombre de stages par encadrant

        SELECT Encadrant, COUNT(*)
        FROM Stage
        GROUP BY Encadrant
  • Les stages sont regroupés par encadrant : 1 groupe par encadrant + 1 groupe pour les stages sans encadrant.
  • Pour chacun de ces groupes, le nom de l'encadrant est projeté, ainsi que l'effectif du groupe (qui correspondant au nombre de stages de l'encadrant).
  • Le SELECT contient la colonne du GROUP BY, ainsi qu'une fonction d'agrégation.

Définition : sélection/restriction des groupes

  • Il est possible d'éliminer certains groupes avant la phase de projection des expressions de groupe et des fonctions d'agrégation (par le SELECT).
  • Grâce à la clause HAVING, qui suit immédiatement la clause GROUP BY.
  • Cette clause agit pour les groupes de la même manière que WHERE agit pour les enregistrements. Notez que la clause WHERE opère avant le GROUP BY, et donc avant le HAVING.

Exemple de restriction de groupe : liste des encadrants ayant moins de 2 stages, par ordre alphabétique

        SELECT Encadrant
        FROM Stage
        WHERE Encadrant IS NOT NULL
        GROUP BY Encadrant
        HAVING COUNT(*)<=2
        ORDER BY Encadrant