IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Implémentation d'une jointure "rien=tout"


Sujet :

Langage SQL

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 6
    Points : 6
    Points
    6
    Par défaut Implémentation d'une jointure "rien=tout"
    Bonjour
    Veuillez excuser pour le sujet pas trés explicite mais si vous trouvez mieux vous pouvez le proposer.

    Je me pose une question sur l'implémentation d'un modèle de données :
    Une rubrique peut être filtrée par plusieurs catégories et bien sur une catégorie peut filtrer plusieurs rubriques.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CREATE TABLE rubrique (id_rubrique INT, libelle VARCHAR(255), PRIMARY KEY (id_rubrique));
    CREATE TABLE categorie (id_categorie INT, libelle VARCHAR(255), PRIMARY KEY (id_categorie));
    CREATE TABLE filtre_rubrique(id_rubrique INT, id_categorie INT);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    INSERT INTO rubrique (1, 'rubrique pour les ouvriers');
    INSERT INTO rubrique (2, 'rubrique pour toutes les catégories');
    INSERT INTO categorie (1, 'Ouvrier');
    INSERT INTO categorie (2, 'Cadre');
    INSERT INTO filtre_rubrique (1,1);
    Le problème est que si une rubrique ne possède aucun filtre, c'est comme si elle était filtrée par toutes les catégories. Ainsi la rubrique avec l'id 2 devrait apparaître tout le temps.
    Pour réaliser ceux ci nous avons donc décidé que créer la vue suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE VIEW rubrique_avec_filtre AS 
    SELECT r.*, c.id_categorie 
    FROM rubrique r
    LEFT JOIN filtre_rubrique fr ON r.id_rubrique=fr.id_rubrique
    LEFT JOIN categorie c ON !isnull(fr.id_categorie) AND c.id_categorie=fr.id_categorie OR isnull(fr.id_categorie);
    Est ce à votre avis une bonne implémentation du problème ou vaut il mieux créer pour chaque rubrique, un enregistrement pour chaque categorie dans la table filtre ?

    Merci d'avance pour vos solutions
    La feuil

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 874
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 874
    Points : 53 048
    Points
    53 048
    Billets dans le blog
    6
    Par défaut
    1) votre modèle est incomplet

    2) votre requête est incorrecte

    Voici une solution

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    CREATE TABLE rubrique 
    (id_rubrique INT NOT NULL,
     libelle     VARCHAR(16),
     PRIMARY KEY (id_rubrique))
     
    CREATE TABLE categorie 
    (id_categorie INT NOT NULL,
     libelle      VARCHAR(16),
     PRIMARY KEY (id_categorie))
     
    CREATE TABLE filtre_rubrique
    (id_rubrique  INT NOT NULL FOREIGN KEY REFERENCES rubrique (id_rubrique), 
     id_categorie INT NOT NULL FOREIGN KEY REFERENCES categorie (id_categorie), 
     PRIMARY KEY (id_rubrique, id_categorie))
     
    INSERT INTO rubrique VALUES (1, 'la mécanique')
    INSERT INTO rubrique VALUES (2, 'la cuisine')
     
    INSERT INTO categorie VALUES (1, 'Ouvrier')
    INSERT INTO categorie VALUES (2, 'Cadre')
     
    INSERT INTO filtre_rubrique VALUES  (1,1)
     
     
    CREATE VIEW rubrique_avec_filtre AS
    SELECT r.id_rubrique, c.id_categorie, r.libelle as rubrique, c.libelle as categorie, 
           CASE 
              WHEN fr.id_rubrique IS NULL THEN 'NON'
              ELSE 'OUI'
           END AS FILTRE
    FROM   rubrique r
           CROSS JOIN categorie c 
           LEFT OUTER JOIN filtre_rubrique fr 
                ON  r.id_rubrique = fr.id_rubrique
                AND c.id_categorie = fr.id_categorie
     
    SELECT *
    FROM   rubrique_avec_filtre
     
    id_rubrique id_categorie rubrique         categorie        FILTRE 
    ----------- ------------ ---------------- ---------------- ------ 
    1           1            la mécanique     Ouvrier          OUI
    1           2            la mécanique     Cadre            NON
    2           1            la cuisine       Ouvrier          NON
    2           2            la cuisine       Cadre            NON
    ! et isnull n'existe pas en SQL... C'est propre à votre SGBDR.

    A +

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Je suis d'accord que mon modèle était incomplet et que ma requête n'était pas trés normalisée.
    Mais je pense que l'on sait mal compris sur le problème.
    Reprenons ton modèle qui est parfaitement correct par rapport au miens.
    Voila donc le contenu de la base :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    INSERT INTO rubrique VALUES (1, 'la mécanique');
    INSERT INTO rubrique VALUES (2, 'la cuisine');
     
    INSERT INTO categorie VALUES (1, 'Ouvrier');
    INSERT INTO categorie VALUES (2, 'Cadre');
     
    INSERT INTO filtre_rubrique VALUES  (1,1);
    Maintenant, prenons comme exemple la rubrique 2 ("la cuisine") à laquelle nous n'appliquons aucun filtre.
    2 solutions s'offrent à nous :
    • Soit on peut ajouter toutes les categories existantes au filtre et ainsi on aurait comme enregistrements dans la table filtre_rubrique :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      INSERT INTO filtre_rubrique VALUES  (2,1); 
      INSERT INTO filtre_rubrique VALUES  (2,2);

    • Soit on crée une vue qui va vérifier qu'il n'existe pas de filtre sur une rubrique et qui va alors rechercher toutes les catégories existantes :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      CREATE VIEW rubrique_avec_filtre AS
      SELECT r.id_rubrique, c.id_categorie, r.libelle as rubrique, c.libelle as categorie
      FROM rubrique r
      LEFT JOIN filtre_rubrique fr
                ON r.id_rubrique=fr.id_rubrique
      INNER JOIN categorie c ON fr.id_categorie=c.id_categorie OR fr.id_categorie IS NULL;
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      SELECT *
      FROM   rubrique_avec_filtre
       
      id_rubrique id_categorie rubrique         categorie
      ----------- ------------ ---------------- ----------------
      1           1            la mécanique     Ouvrier
      2           1            la cuisine       Ouvrier
      2           2            la cuisine       Cadre


    Ma question était : Quelle est l'implémentation la plus élégante ? Ou existe t'il une autre méthode ? Ou est ce que je suis totalement à côté de la plaque ?
    Sachant aussi que la deuxième méthode à l'avantage de rajouter les catégories automatiquement au filtre si on en rajoute une.

    La feuil

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 874
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 874
    Points : 53 048
    Points
    53 048
    Billets dans le blog
    6
    Par défaut
    la vue que je vous ais donné permet de savoir si vous avez un filtre ou pas en français. Libre à vous de l'utiliser comme bon vous semble dans n'importe quelle autre requête !!!!!

    A +

Discussions similaires

  1. [.NET] Le ReportView n'affiche rien lorsque je fais une jointure
    Par AsPrO dans le forum SAP Crystal Reports
    Réponses: 4
    Dernier message: 30/08/2008, 10h41
  2. jointure qui retourne tout sur une seule ligne
    Par Ralfman68 dans le forum Requêtes
    Réponses: 9
    Dernier message: 12/10/2007, 21h52
  3. supprimer une table qui a des quotes dans son nom
    Par kleenex dans le forum Access
    Réponses: 2
    Dernier message: 17/10/2005, 16h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo