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 :

Une requête trop complexe pour moi


Sujet :

Langage SQL

  1. #1
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut Une requête trop complexe pour moi
    Bonjour,
    je révise les bases de données, notamment ce soir le langage SQL. Il m'est demandé d'extraire en une requête tous les sculpteurs qui ont au moins une œuvre au Louvre et aucune à Orsay.

    Voici la structure de la base considérée :
    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
    musee (
      nomM varchar(32) collate latin1_general_ci NOT NULL,
      ville varchar(64) collate latin1_general_ci NOT NULL,
      pays varchar(32) collate latin1_general_ci NOT NULL,
      N_Obj int(11) NOT NULL,
      Theme varchar(128) collate latin1_general_ci NOT NULL,
      PRIMARY KEY  (nomM,N_Obj),
      KEY N_Obj (N_Obj)
     
    sculpteurs (
      N_Auteur int(10) unsigned zerofill NOT NULL auto_increment,
      nom varchar(32) collate latin1_general_ci NOT NULL,
      prenom varchar(32) collate latin1_general_ci NOT NULL,
      PRIMARY KEY  (N_Auteur)
    )
     
    sculptures (
      N_Obj int(10) unsigned zerofill NOT NULL auto_increment,
      titre varchar(32) collate latin1_general_ci NOT NULL,
      description varchar(128) collate latin1_general_ci NOT NULL,
      datecreation date NOT NULL,
      prix int(11) NOT NULL,
      valeurachat int(11) NOT NULL,
      dateachat date NOT NULL,
      N_Auteur int(10) unsigned zerofill NOT NULL,
      PRIMARY KEY  (N_Obj),
      KEY titre (titre,N_Auteur)

    Faut-il utiliser un outil particulier autre que les select, from, where, distinct et group by ? Si oui pouvez-vous me donner cette fameuse requête ?

    D'avance merci.




    Edit :
    J'ai bien une solution, mais je la trouve très peu élégante (j'ai fini par me souvenir de la clause having
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    SELECT nom, prenom
    FROM sculpteurs AS a, (
       SELECT DISTINCT N_Auteur, nomM
       FROM sculptures AS s, (
          SELECT N_Obj, nomM
          FROM musee
          WHERE nomM = "Louvre"
             OR nomM = "Orsay"
          ) AS a
       WHERE s.N_Obj = a.N_Obj
       GROUP BY N_Auteur
       HAVING nomM <> "Orsay"
    ) AS s
    WHERE a.N_Auteur = s.N_Auteur

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 242
    Points : 12 874
    Points
    12 874
    Par défaut
    Bonjour,
    Perso j'aurai fait ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    select distinct sculpteur.nom
    from sculpteur
    inner join scultpure on sculpture.n_auteur = sculpteur.n_auteur
    inner join musee on musee.n_objet sculpture.n_objet
    where musee.nomN = 'LOUVRE'
    and not exists(select * from from sculpteur
    inner join scultpure on sculpture.n_auteur = sculpteur.n_auteur
    inner join musee on musee.n_objet sculpture.n_objet
    where musee.nomN = 'ORSAY')
    Tu peux aussi le faire avec un Except au lieu du not exists.

    Tatayo

  3. #3
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 048
    Points
    34 048
    Billets dans le blog
    14
    Par défaut
    Il me semble qu'il y a une erreur de conception...

    'N_Obj' est la clé primaire de la table 'sculptures'. On retrouve cette colonne 'N_Obj' dans la table 'musee' associée à nomM pour en former la clé primaire.

    Alors ou bien chaque musée ne contient qu'une seule oeuvre, ce qui me semble peu, ou bien les tables musee et sculptures sont redondantes puisqu'on va retrouver autant d'objets dans musee qu'il y en a dans sculptures !

    Revenons en arrière vers la conception :
    Règle de gestion :
    Une sculpture est exposée dans un seul musée et un musée expose plusieurs sculptures.

    MCD :
    Musee -0,n----Exposer----1,1- Sculpture

    La clé primaire du musée devient clé étrangère dans la table sculptures et pas l'inverse !

    Je vous conseille aussi de ne pas utiliser le nom du musée comme clé primaire mais un identifiant de type entier auto-incrémenté, comme vous l'avez fait pour sculptures.

  4. #4
    Membre actif Avatar de hazamor
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2008
    Messages
    179
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2008
    Messages : 179
    Points : 206
    Points
    206
    Par défaut Not Exists et Exists
    La remarque de CinePhil est correcte, càd "Id_musee" l'identifiant de musée est un clé étrangère dans sculpture et cen'est pas l'inverse.
    Supposons que vous avez corrigé cette faut de conception, je vous propose:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    select sculpteur.nom
    from sculpteur S
    where not exists(select 1 from  sculpture SE 
                         where SE.n_auteur = S.n_auteur
                         and musee.Id_musee =SE.Id_musee
                         and musee.nom = 'ORSAY')
    and exists(select 1 from  sculpture SE 
                         where SE.n_auteur = S.n_auteur
                         and musee.Id_musee =SE.Id_musee
                         and musee.nom = 'LOUVRE')

  5. #5
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 858
    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 858
    Points : 52 996
    Points
    52 996
    Billets dans le blog
    6
    Par défaut
    SELECT nom, prenom
    FROM sculpteurs AS a, (
    SELECT DISTINCT N_Auteur, nomM
    FROM sculptures AS s, (
    SELECT N_Obj, nomM
    FROM musee
    WHERE nomM = "Louvre"
    OR nomM = "Orsay"
    ) AS a
    WHERE s.N_Obj = a.N_Obj
    GROUP BY N_Auteur
    HAVING nomM <> "Orsay"
    ) AS s
    WHERE a.N_Auteur = s.N_Auteur
    Dans votre requête l'utilisation des clauses GROUP BY et HAVING est stupide car vous n'avez pas de calculs d'agrégats. En aucun cas ces clauses ne doivent être utilisé sans les fonctions MAX, MIN, AVG, COUNT...

    La réponse étant :
    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
     
     
    SELECT S.nom
    FROM   sculpteur S
           INNER JOIN sculpture SC
                 ON S.N_auteur = SC.N_auteur
           INNER JOIN musee M 
                 ON SC.N_obj = M.N_obj
    WHERE  M.NomM = 'Louvre'
    AND    NOT EXISTS(SELECT *
                      FROM   sculpture SC2
                             INNER JOIN musee M2
                                   ON SC2.N_obj = M2.N_obj
                      WHERE  M2.nomM = 'ORSAY'
                      AND    SC2.N_auteur = SC.N_auteur)

    A +

  6. #6
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut
    Bonjour.
    Merci de vous pencher un peu sur mon problème. En effet, la base est redondante ... mais elle est donnée telle quelle dans l'énoncé. L'exercice suivant est, si je me souviens bien, de l'optimiser.

    Ensuite, concernant votre proposition, ne demande-t-elle pas plus de travail au SGDB qui doit se taper deux fois une double inner join sans restriction avant ?

    Merci encore.

  7. #7
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 048
    Points
    34 048
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par prgasp77 Voir le message
    Ensuite, concernant votre proposition, ne demande-t-elle pas plus de travail au SGDB qui doit se taper deux fois une double inner join sans restriction avant ?
    Il ne faut pas prendre l'ordre d'écriture de la requête pour l'ordre que suivra le SGBD pour l'exécuter.
    L'optimiseur du SGBD se débrouille avec la structure de la requête pour trouver l'ordre adéquat pour faire les choses le plus rapidement possible.

    Dans le cas présent il est probable qu'il commence par appliquer la restriction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE  M.NomM = 'Louvre'
    Afin de limiter le nombre de lignes dans la jointure.

  8. #8
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut
    En gros j'ai un chat pitre entier sur l'optimisation des requetes ... qui ne sert à rien \o/ cours de merde !

    Bon, j'ai passé mon exam aujourd'hui, ça s'est plutôt bien déroulé (il était facile). Au programme, normalisation et arbres d'index ... pas de SQL.

    Merci à vous pour vos réponses.

  9. #9
    Membre émérite Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Points : 2 845
    Points
    2 845
    Par défaut
    Salut !

    Non, les cours ne sont pas (complètement) inutiles.
    Malgré les progrès constants des optimiseurs, connaître les principes de base permet aussi de comprendre plus facilement l'optimiseur. Car celui-ci peut prendre les mauvaises décisions.
    Par ailleurs, entre plusieurs écritures possibles pour une requête, même si le résultat est le même, le plan d'exécution choisi ne sera pas forcément le même : la manière dont on écrit les requêtes à (pour l'instant) toujours encore un impact sur les temps d'exécution !

  10. #10
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut
    Ha ?
    Et est-il possible de comparer deux version d'une même requête (outre le temps d'exécution qui est assez aléatoire) ?

    Merci.

  11. #11
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 101
    Points : 28 398
    Points
    28 398
    Par défaut
    En regardant les plans d'exécution (EXPLAIN PLAN)

  12. #12
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 858
    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 858
    Points : 52 996
    Points
    52 996
    Billets dans le blog
    6
    Par défaut
    Mieux que les plans de requête le plus simple est de demander les statistiques de consommation des ressources. Le premier niveau consiste à comparer globalement les IO de cheque requête. Exemple :
    Sur SQL Server.

    Ensuite à nombre d'IO comparable, il faut voir la consommation CPU de la requête.

    A +

  13. #13
    Membre émérite
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306
    Points : 2 466
    Points
    2 466
    Par défaut
    #1193 - Unknown system variable 'STATISTICS'

    Je crois que MySql ne l'autorise pas ... et je n'ai pas dee serveur sql sous la main .

    Merci tout de même.

  14. #14
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 858
    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 858
    Points : 52 996
    Points
    52 996
    Billets dans le blog
    6
    Par défaut
    MySQL est très pauvre en outils de tuning !

    A +

Discussions similaires

  1. Requête trop complexe pour moi
    Par dauhik dans le forum Requêtes
    Réponses: 10
    Dernier message: 12/11/2012, 13h57
  2. Requête trop complexe pour moi
    Par snips67 dans le forum Requêtes
    Réponses: 6
    Dernier message: 27/01/2010, 09h24
  3. Tri complexe trop complexe pour moi
    Par nemo67 dans le forum Développement
    Réponses: 4
    Dernier message: 18/12/2009, 14h03
  4. Une requête bien compliquée pour moi
    Par bellande dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 01/02/2007, 21h51
  5. Simplication d'une requête "trop complexe"
    Par Manopower dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 27/06/2006, 14h22

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