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 :

Requête spéciale dans le cas d'une relation plusieurs à plusieurs


Sujet :

Langage SQL

  1. #1
    Membre expert
    Avatar de Chauve souris
    Homme Profil pro
    amateur (éclairé ?)
    Inscrit en
    Novembre 2005
    Messages
    1 186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : Paraguay

    Informations professionnelles :
    Activité : amateur (éclairé ?)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 1 186
    Points : 3 086
    Points
    3 086
    Par défaut Requête spéciale dans le cas d'une relation plusieurs à plusieurs
    * Bonjour, *

    Je sèche sur la finalisation d'une requête finale et je sollicite vos avis éclairés.

    Voila le problème (pédagogique)

    1. Une bête table Auteurs, avec une clé AuteurID, prénom, nom, etc.
    2. Une non moins bête table Ouvrages, avec une clé OuvrageID, titre, sous-titre et champ AuteurID pour faire la relation un à plusieurs

    D'emblée cela ne va pas s'il y a plusieurs auteurs pour un ouvrage. Et la relation plusieurs à plusieurs nécessite une troisième table
    3. Coauteurs, avec une clé CoauteursID, avec les champs AuteurID et OuvrageID

    Pas de souci si ce n'est que je suis infichu de faire une requête (ou un formulaire) qui ne considère pas qu'il y a un ouvrage, du même titre, pour chaque auteur ou, inversement, que chaque auteur a écrit un ouvrage du même titre

    Comment faire un regroupement ? Avec un champ calculé qui mette les auteurs sur la même ligne ?

    Ceci dans le cas du SQL purédur. Mais peut-être que cela n'est pas possible en SQL et qu'il faille passer par de la programmation

    Dans tous les cas je pense qu'il doit bien y avoir un tutoriel à ce sujet. Le SGBD importe peu, j'ai tout qui cohabite dans mon ordi (MySQL, Access, SQLServer, PostgreSQL) tout ça sous Windows, le septième du nom.

    * Merci *
    "Toute l'histoire de l'informatique n'a été que l'histoire des systèmes d'exploitations" (Le Manifeste du PC)

  2. #2
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    Il est possible de faire cela en SQL, néanmoins ce n'est pas une opération "naturelle" pour SQL, et idéalement, il vaut mieux traiter le regroupement dans votre application. Quelles données voulez vous présenter, et comment ?

  3. #3
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 775
    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 775
    Points : 52 747
    Points
    52 747
    Billets dans le blog
    5
    Par défaut
    Tout d'abord votre modèle est faux. Voici un modèle correct pour ce faire :

    Une table des auteurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CREATE TABLE T_AUTEURS_ATR
    (ATR_ID            INT PRIMARY KEY,
     ATR_NOM           VARCHAR(32));
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    INSERT INTO T_AUTEURS_ATR 
    VALUES (1, 'Boileau'),
           (2, 'narcejac'),
           (3, 'Simenon');
    -- une table des ouvrages
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CREATE TABLE T_OUVRAGE_AVG
    (OVG_ID            INT PRIMARY KEY,
     OVG_TITRE         VARCHAR(256));
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    INSERT INTO T_OUVRAGE_AVG 
    VALUES (1000, 'D''entre les morts'),
           (1001, 'Maigret voit rouge');
    -- une table de jointure ouvrages/auteurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CREATE TABLE T_J_OUVRAGE_AUTEUR_JOA
    (OVG_ID            INT NOT NULL REFERENCES T_OUVRAGE_AVG (OVG_ID),
     ATR_ID            INT NOT NULL REFERENCES T_AUTEURS_ATR (ATR_ID),
     CONSTRAINT PK_JOA PRIMARY KEY (ATR_ID, OVG_ID));
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    INSERT INTO T_J_OUVRAGE_AUTEUR_JOA
    VALUES (1000, 1),
           (1000, 2),
           (1001, 3);
    -- la requête (récursive) donnant le liste des auteurs par ouvrage
    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
    WITH T0 AS
    (       
    SELECT *, ROW_NUMBER() OVER(PARTITION BY OVG_ID ORDER BY ATR_ID) AS NUM,
              ROW_NUMBER() OVER(PARTITION BY OVG_ID ORDER BY ATR_ID DESC) AS MUN
    FROM   T_J_OUVRAGE_AUTEUR_JOA
    ),
    T1 AS
    (
    SELECT OVG_ID, CAST(ATR_NOM AS VARCHAR(8000)) AS NOMS, NUM, MUN
    FROM   T0
           INNER JOIN T_AUTEURS_ATR AS A
                 ON T0.ATR_ID = A.ATR_ID
    WHERE  NUM = 1
    UNION ALL
    SELECT T1.OVG_ID, NOMS + ', ' + A.ATR_NOM, T0.NUM, T1.MUN
    FROM   T1
           INNER JOIN T0 
                 On T1.OVG_ID = T0.OVG_ID
                    AND T0.NUM - 1 = T1.NUM
           INNER JOIN T_AUTEURS_ATR AS A
                 ON T0.ATR_ID = A.ATR_ID)
    SELECT OVG_TITRE, NOMS 
    FROM   T1
           INNER JOIN T_OUVRAGE_AVG AS O
                 ON T1.OVG_ID = O.OVG_ID
    WHERE NUM = MUN;
    La réponse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    OVG_TITRE                 NOMS
    ------------------------- -----------------------
    Maigret voit rouge        Simenon
    D'entre les morts         Boileau, narcejac
    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  4. #4
    Membre expert
    Avatar de Chauve souris
    Homme Profil pro
    amateur (éclairé ?)
    Inscrit en
    Novembre 2005
    Messages
    1 186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : Paraguay

    Informations professionnelles :
    Activité : amateur (éclairé ?)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 1 186
    Points : 3 086
    Points
    3 086
    Par défaut Je vais voir ça !
    Un grand merci pour cette réponse détaillée je vais mettre ça en pratique !
    Car j'avais pris la (mauvaise ?) habitude de faire ce type de regroupement dans un état Access.
    "Toute l'histoire de l'informatique n'a été que l'histoire des systèmes d'exploitations" (Le Manifeste du PC)

  5. #5
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 002
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 002
    Points : 30 907
    Points
    30 907
    Billets dans le blog
    16
    Par défaut
    En passant...


    Frédéric, tu es bien sévère...

    Chauve souris, une remarque en passant :

    Certes, SQLpro est sévère quand il dit que votre modèle est faux mais celui-ci mérite quand même un aménagement. En l’état, votre table Coauteurs comporte deux clés candidates :
    {AuteurID, OuvrageID}

    {CoauteursID}
    Dans la série « surcharge pondérale », disons que la clé {CoauteursID} est superflue et peut passer au fil du rasoir d’Ockham, auquel cas on obtient une structure équivalente à celle recommandée par SQLpro.

    Le problème qui s'est présenté était seulement celui de la présentation sur une seule ligne de la liste des coauteurs en SQL (c'est de la cosmétique comme dirait al1_24), d’où — quand le SGBD le permet — l’utilisation de la jointure récursive, voire de la technique XML Path façon mikedavem.
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  6. #6
    Membre expert
    Avatar de Chauve souris
    Homme Profil pro
    amateur (éclairé ?)
    Inscrit en
    Novembre 2005
    Messages
    1 186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : Paraguay

    Informations professionnelles :
    Activité : amateur (éclairé ?)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 1 186
    Points : 3 086
    Points
    3 086
    Par défaut Ca marche !
    Testé sur SQL Server 2012 Express.

    Je reconnais que la table Coauteurs était mal foutue et que la PRIMARY KEY peut se faire avec les deux ID de la table.

    Et surtout que j'étais infichu d'écrire la requête pour extraire ce que je voulais.
    "Toute l'histoire de l'informatique n'a été que l'histoire des systèmes d'exploitations" (Le Manifeste du PC)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. calcul préavis dans le cas d'une période d'essai renouvelée
    Par benlabasse dans le forum Démission
    Réponses: 6
    Dernier message: 22/02/2008, 14h18
  2. cas d'une relation 1,n de chaque coté
    Par Zak Blayde dans le forum Modélisation
    Réponses: 3
    Dernier message: 18/12/2007, 10h51
  3. Réponses: 1
    Dernier message: 23/11/2007, 12h04
  4. DRY dans le cas d'une relation 1-N
    Par titoumimi dans le forum Ruby on Rails
    Réponses: 15
    Dernier message: 02/05/2007, 05h48
  5. [cast] dans le cas d'une Std::list
    Par ZaaN dans le forum SL & STL
    Réponses: 9
    Dernier message: 26/10/2006, 10h07

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