Fichier de rejeu Close

Indication Close

A propos de... Close

Commentaire Close

Systèmes d'Information

  • Notions mathématiques
  • Calcul relationnel
  • Algèbre relationnelle
  • Langage de requêtes
  • Arbre de requêtes
  • QCM
  • Introduction
  • Commandes de bases
  • Langage de définition de données
  • Types de données
  • Requêtes
  • Présentation
  • Calcul relationnel
  • Algèbre relationnelle
  • Division relationnelle
  • Dépendances fonctionnelles
  • Décomposition de relations
  • Inférence logique
  • Normalisation
  • Aux pays des bières
  • Modélisation
  • Exercices
  • Présentation
  • Aux pays des bières
  • Au Tournoi des six nations
  • Salles de concerts
  • Définitions
  • Langage SQL
  • Modèle relationnel
  • Films
  • Repas
  • Repas
Index

Téléchargements

  • Site
  • Sources
  • EniBook
logo

Crédits

© Your Copyright

Aide

En-tête

MenuContenu
Sommaire,
Téléchargements
Aide sur les outils

Pied de page

ChevronAction
Aller en haut de la page courante
Aller en bas de la page courante
Passer à la page précédente
Passer à la page suivante

Division relationnelle

5/5 Aux pays des bières : division relationnelle
  1. NOT EXISTS, EXCEPT
    • Question
    • Solution
    Construire un arbre de requêtes répondant à la question :
    • \(Q_1\) : « quels sont les identifiants des bars qui servent toutes les bières ? ».
    Votre réponse :
    Arbre de requêtes : graph87.json

    Tables

    Opérateurs unaires

    Opérateurs binaires

    Vue d'ensemble
    id_bar
    1
    Une solution possible :

    On utilise l’opérateur de division relationnelle (\(\div\)) pour trouver dans la table des services les identifiants des bars (id_bar) liés à tous les identifiants des bières (id_biere) de la table des bieres.

    Ecriture en algèbre relationnelle :
    • \(\displaystyle Q_1 = {\LARGE\div}(\Pi_{(id\_bar,id\_biere)}(services),\Pi_{(id\_biere)}(bieres))\).

    L’opérateur de division relationnelle entre deux tables (\(S,T\)) permettant de récupérer les éléments \(X\) de l’ensemble \(S\) qui sont liés à tous les éléments \(Y\) de l’ensemble \(T\) :

    • \(R=\div(S(X,Y),T(Y))\)

    Cet opérateur n’existe pas en SQL mais peut être représenté à l’aide d’opérateurs de base par une requête imbriquée (NOT EXISTS) avec une opération ensembliste de différence (EXCEPT).

    Ecriture en SQL :

    SELECT se.X
    FROM S se
    WHERE NOT EXISTS (
                      (SELECT Y FROM T)
                      EXCEPT
                      (SELECT Y FROM S si WHERE si.X=se.X)
                     );
    

    Ce qui se traduit par :

    • « récupérer les \(X\) de \(S\) pour lesquels la différence entre le nombre total des \(Y\) de \(T\) et ceux de \(S\) est nulle »

    Dans le contexte des « bars qui servent des bières » :

    SELECT DISTINCT se.id_bar
    FROM  services se
    WHERE NOT EXISTS (
                      SELECT id_biere FROM bieres
                      EXCEPT
                      SELECT id_biere FROM services si WHERE si.id_bar=se.id_bar
                     );
    

    Ce qui se traduit par :

    • « récupérer les identifiants (\(id\_bar\)) des \(services\) pour lesquels la différence entre le nombre total des identifiants (\(id\_biere\)) de \(bieres\) et ceux des \(services\) est nulle »
    Arbre de requêtes : bars-11-1.json

    Tables

    Opérateurs unaires

    Opérateurs binaires

    Vue d'ensemble
    id_bar
    1
  2. DOUBLE NEGATION (NOT EXISTS)
    • Question
    • Solution
    Construire un arbre de requêtes répondant à la question :
    • \(Q_1\) : « quels sont les noms des bars qui servent toutes les bières ? ».
    Votre réponse :
    Arbre de requêtes : graph94.json

    Tables

    Opérateurs unaires

    Opérateurs binaires

    Vue d'ensemble
    bar
    Bar du Coin
    Une solution possible :

    On utilise d’abord l’opérateur de division relationnelle (\(\div\)) pour trouver dans la table des services les identifiants des bars (id_bar) liés à tous les identifiants des bières (id_biere) de la table des bieres.

    On utilise le résultat obtenu pour faire une jointure naturelle avec l’ensemble des bars.

    On récupère au final le nom des bars qui servent toutes les bières en faisant une projection sur l’attribut bar du résultat précédent.

    Ecriture en algèbre relationnelle :

    • \(\displaystyle Q_1 = \Pi_{(bar)}(\Join_{[]}(bars,{\LARGE\div}(\Pi_{(id\_bar,id\_biere)}(services),\Pi_{(id\_biere)}(bieres))))\).

    Ecriture en SQL :

    SELECT bar
    FROM bars ba NATURAL JOIN services se
    WHERE
    NOT EXISTS (
                SELECT *
                FROM bieres bi
                WHERE NOT EXISTS(
                                 SELECT *
                                 FROM services  si
                                 WHERE si.id_biere=bi.id_biere
                                   AND se.id_bar=si.id_bar
                                )
              );
    

    En SQL la jointure entre les services et les bars peut se faire dans la requête imbriquée et permet d’éviter une auto-jointure sur la table des services.

    SELECT *
    FROM bars ba WHERE
    NOT EXISTS(
               SELECT *
               FROM bieres bi
               WHERE NOT EXISTS(
                                SELECT *
                                FROM services s
                                WHERE s.id_bar=ba.id_bar
                                  AND s.id_biere=bi.id_biere
                               )
              );
    
    Arbre de requêtes : bars-11-2.json

    Tables

    Opérateurs unaires

    Opérateurs binaires

    Vue d'ensemble
    bar
    Bar du Coin
  3. GROUP BY, HAVING, COUNT (1/3)
    • Question
    • Solution
    Construire un arbre de requêtes répondant à la question :
    • \(Q_1\) : « quels sont les identifiants des bars qui servent toutes les bières ? ».
    Votre réponse :
    Arbre de requêtes : graph101.json

    Tables

    Opérateurs unaires

    Opérateurs binaires

    Vue d'ensemble

    <table class= »sql-table » query= »Q_1 »> <thead> <tr><th>id_equipe</th><th>nom</th></tr> </thead> <tbody> <tr><td>FRA</td><td>Lopez</td></tr> </tbody> </table>

    Une solution possible :

    On peut aussi mettre en œuvre la division relationnelle pour récupérer les identifiants des bars qui servent toutes les bières en regroupant les services par identifiant de bar :

    • GROUP BY id_bar

    puis en vérifiant que le nombre de bières différentes servies par les bars en question sont égales au nombre total de bières existantes dans la base de données :

    • COUNT(DISTINCT id_biere) = (SELECT COUNT(id_biere) FROM bieres)

    Ecriture en algèbre relationnelle :

    • \(Q = G_{[COUNT(id\_biere)=(SELECT \; COUNT(id\_biere)\; FROM \; bieres)]}^{(id\_bar)}(services)\).

    Le symbole \(G\) représente l’opérateur de regroupement appliqué sur la table services :

    • en exposant : attributs de regroupement (GROUP BY)
    • en indice : critère de restriction (clause HAVING) sur les regroupements.

    Ecriture en SQL :

    SELECT id_bar
    FROM services
    GROUP BY id_bar
    HAVING COUNT(DISTINCT id_biere) = (SELECT COUNT(id_biere) FROM bieres);
    
    Arbre de requêtes : bars-11-3.json

    Tables

    Opérateurs unaires

    Opérateurs binaires

    Vue d'ensemble

    <table class= »sql-table » query= »Q_1 »> <thead> <tr><th>id_equipe</th><th>nom</th></tr> </thead> <tbody> <tr><td>FRA</td><td>Lopez</td></tr> </tbody> </table>

  4. GROUP BY, HAVING, COUNT (2/3)
    • Question
    • Solution
    Construire un arbre de requêtes répondant à la question :
    • \(Q_1\) : « quels sont les noms des bars qui servent toutes les bières ? ».
    Votre réponse :
    Arbre de requêtes : graph108.json

    Tables

    Opérateurs unaires

    Opérateurs binaires

    Vue d'ensemble
    bar
    Bar du Coin
    Une solution possible :

    On met en œuvre la division relationnelle pour récupérer les identifiants des bars qui servent toutes les bières en regroupant les services par identifiant de bar :

    • GROUP BY id_bar

    puis en vérifiant que le nombre de bières différentes servies par les bars en question sont égales au nombre total de bières existantes dans la base de données :

    • COUNT(DISTINCT id_biere) = (SELECT COUNT(id_biere) FROM bieres)

    Ecriture en algèbre relationnelle :

    • \(Q = G_{[COUNT(id\_biere)=(SELECT \; COUNT(id\_biere)\; FROM \; bieres)]}^{(id\_bar)}(services)\).

    On utilise le résultat obtenu pour faire une jointure naturelle avec l’ensemble des bars.

    • \(NJ = \Join_{[]}(A,bars)\).

    On récupère au final le nom des bars en projetant sur l’attribut bar du résultat précédent.

    • \(Q_1 = \Pi_{(bar)}(NJ)\).

    Ecriture en SQL :

    SELECT bar
    FROM services NATURAL JOIN bars
    GROUP BY bar
    HAVING COUNT(DISTINCT id_biere) = (SELECT COUNT(id_biere) FROM bieres);
    
    Arbre de requêtes : bars-11-4.json

    Tables

    Opérateurs unaires

    Opérateurs binaires

    Vue d'ensemble
    bar
    Bar du Coin
  5. GROUP BY, HAVING, COUNT (3/3)
    • Question
    • Solution
    Construire un arbre de requêtes répondant à la question :
    • \(Q_1\) : « identifiant des bars et nombre de bières des bars qui servent toutes les bières ? ».
    Votre réponse :
    Arbre de requêtes : graph115.json

    Tables

    Opérateurs unaires

    Opérateurs binaires

    Vue d'ensemble
    id_barcount(id_biere)
    18
    Une solution possible :

    On met en œuvre la division relationnelle pour récupérer les identifiants des bars qui servent toutes les bières en regroupant les services par identifiant de bar :

    • GROUP BY id_bar

    puis en vérifiant que le nombre de bières différentes servies par les bars en question sont égales au nombre total de bières existantes dans la base de données :

    • COUNT(DISTINCT id_biere) = (SELECT COUNT(id_biere) FROM bieres)

    On peut alors appliquer les fonctions d’agrégats (COUNT(id_biere)) pour calculer le nombre de bières servies par ces bars.

    Ecriture en algèbre relationnelle :

    • \(A = G_{[COUNT(id\_biere)=(SELECT \; COUNT(id\_biere)\; FROM \; bieres)]}^{(id\_bar,COUNT(id\_biere))}(services)\).

    Ecriture en SQL :

    SELECT id_bar,count(id_biere)
    FROM services
    GROUP BY id_bar
    HAVING COUNT(DISTINCT id_biere) = (SELECT COUNT(id_biere) FROM bieres);
    
    Arbre de requêtes : bars-11-5.json

    Tables

    Opérateurs unaires

    Opérateurs binaires

    Vue d'ensemble
    id_barcount(id_biere)
    18
 
Systèmes d'Information : Division relationnelle, 12 févr. 2018.