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

MySQL Discussion :

Aide sur une méthode de requête oubliée


Sujet :

MySQL

  1. #1
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 99
    Points : 74
    Points
    74
    Par défaut Aide sur une méthode de requête oubliée
    Salut à tous,

    J'ai un trou de mémoire sur la méthode à utiliser pour récupérer à l'aide d'une jointure 1,n les lignes qui correspondent à une exclusion...
    Ce n'est pas clair, ok, une petit exemple:

    Je dispose de 3 tables

    Table Classeur
    - Id_Classeur
    Table Jointure_Classeur_Fichiers
    - Id_Classeur
    - Id_Fichier
    Table Fichiers
    - Id_Fichier
    - Nom_Fichier

    Pour l'exemple, on se contentera de dire qu'un classeur peut contenir 0 ou plusieurs fichiers.

    Je voudrais récupérer tous les classeurs qui ne contiennent pas un fichier appelé 'top secret'

    Je suis persuadé de l'avoir déjà fait avec une jointure, mais je ne trouve plus l'astuce, ni même le nom de la méthode.

    Si quelqu'un à deux minutes, merci d'avance !!!

  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,

    Vous pouvez passer par un NOT EXISTS avec une sous requete corrélée.

    Vous pouvez aussi passer par une jointure externe avec vérification de NULL sur la table jointe.

    Vous pouvez aussi utiliser un NOT IN avec sous requête.

  3. #3
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 910
    Points
    38 910
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Bonjour,

    Vous pouvez passer par un NOT EXISTS avec une sous requete corrélée.
    Vous pouvez aussi passer par une jointure externe avec vérification de NULL sur la table jointe.
    Vous pouvez aussi utiliser un NOT IN avec sous requête.
    Pour la 2ème méthode, il faut tester une colonne définie en "not null" (par exemple une clef), qui ne peut donc être "null" que si la jointure n'est pas satisfaite

  4. #4
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 99
    Points : 74
    Points
    74
    Par défaut
    Bonjour à tous,

    Merci pour vos réponses.

    Je vais creuser un peu le NOT IN et le NOT EXIST, mais pour la jointure externe et le test sur le not null je pense que cela ne conviendra pas:

    Si un classeur à un fichier "top secret" et un fichier "projet A", je vais récupérer le classeur, car j'aurai bien ma clef à null pour le fichier "projet A".
    --> A moins qu'effectivement j'ai omis une astuce dans la jointure ou dans la requête.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    SELECT * FROM Classeurs c
    JOIN Jointure_Classeur_Fichier cf ON c.id = cf.id_classeur
    LEFT JOIN Fichiers f ON f.id = cf.id_fichier AND f.name like '%top secret%'
    WHERE f.id is NULL
    GROUP BY c.id
    Je pensais pas avoir tant de mal à retrouver cette requête qui me paraissait si simple...

    Merci pour votre aide.

  5. #5
    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 : 60
    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 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    1) A quoi sert votre GROUP BY ?

    2) Puisque vous faites une jointure externe, vous allez avoir tous les classeurs !

    3) Pour ce genre de besoin, la meilleure solution est le NOT EXISTS.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  6. #6
    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
    Citation Envoyé par Leduc08 Voir le message
    Si un classeur à un fichier "top secret" et un fichier "projet A", je vais récupérer le classeur, car j'aurai bien ma clef à null pour le fichier "projet A".
    Non, il suffit, comme vous l'avez d'ailleurs fait, de mettre la condition "Top secret" dans la condition de jointure (et non dans la clause WHERE). Ainsi la jointure ne se fera pas pour les autres types de dossier.

    Votre requête est donc correcte à ce niveau là. Ce qui ne va pas, c'est votre GROUP BY qui ne fait pas bon ménage avec le SELECT *

  7. #7
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 99
    Points : 74
    Points
    74
    Par défaut
    Merci pour la réponse.

    Citation Envoyé par CinePhil Voir le message
    1) A quoi sert votre GROUP BY ?
    Si je ne fais pas de group by je récupère autant d'id classeur qu'il y a de fichiers, le but était d'avoir uniquement un id par classeur qui ne contient pas de fichier 'top secret'

    Citation Envoyé par CinePhil Voir le message
    2) Puisque vous faites une jointure externe, vous allez avoir tous les classeurs !
    C'est justement ce qui me paraissait poser problème

    Citation Envoyé par CinePhil Voir le message
    3) Pour ce genre de besoin, la meilleure solution est le NOT EXISTS.
    Ok, je vais creuser le NOT EXISTS.

  8. #8
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 99
    Points : 74
    Points
    74
    Par défaut
    Merci pour la réponse.

    Citation Envoyé par aieeeuuuuu Voir le message
    Non, il suffit, comme vous l'avez d'ailleurs fait, de mettre la condition "Top secret" dans la condition de jointure (et non dans la clause WHERE). Ainsi la jointure ne se fera pas pour les autres types de dossier.

    Votre requête est donc correcte à ce niveau là. Ce qui ne va pas, c'est votre GROUP BY qui ne fait pas bon ménage avec le SELECT *
    Même réponse que pour Cinephil, comment procéder alors pour ne récupérer qu'une ligne par classeur concerné?

  9. #9
    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
    arff, je n'avais pas vu qu'il y avait une troisième table, la table associative.

    Il faut donc imbriquer les jointures :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT c.id_classeur
    FROM Classeurs c
    LEFT JOIN Jointure_Classeur_Fichier cf 
            INNER JOIN Fichiers f 
                ON f.id = cf.id_fichier 
                AND f.name like '%top secret%'
        ON c.id = cf.id_classeur
    WHERE f.id is NULL

  10. #10
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 99
    Points : 74
    Points
    74
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    arff, je n'avais pas vu qu'il y avait une troisième table, la table associative.

    Il faut donc imbriquer les jointures :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT c.id_classeur
    FROM Classeurs c
    LEFT JOIN Jointure_Classeur_Fichier cf 
            INNER JOIN Fichiers f 
                ON f.id = cf.id_fichier 
                AND f.name like '%top secret%'
        ON c.id = cf.id_classeur
    WHERE f.id is NULL
    J'étais vraiment confiant sur celle-ci, mais malheureusement non...

    Cette requête me retourne également les classeurs qui ont un fichier 'top secret'.
    --> Je pense que c'est toujours le problème du fichier 'projet A' qui fait que le classeur répond à la condition, même si à la vue de ce que j'ai compris de la requête cela ne devrait pas être le cas. Je vais continuer de creuser dans ce sens.

    J'ai commencé également à regarder le NOT EXIST et le NOT IN.

    Merci pour ton aide.

  11. #11
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 99
    Points : 74
    Points
    74
    Par défaut
    Mes excuses, la requête fonctionne correctement !!!
    Le problème venait de l'interprétation du résultat.

    La notion oubliée était celle de la jointure imbriquée, c'est elle qui fait la différence.
    La solution à ma question est donc:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT c.id_classeur
    FROM Classeurs c
    LEFT JOIN Jointure_Classeur_Fichier cf 
            INNER JOIN Fichiers f 
                ON f.id = cf.id_fichier 
                AND f.name like '%top secret%'
        ON c.id = cf.id_classeur
    WHERE f.id is NULL
    Merci pour votre aide.

  12. #12
    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 : 60
    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 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    La solution avec NOT EXISTS :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT c.id
    FROM Classeurs c
    WHERE NOT EXISTS
    (
        SELECT *
        FROM Jointure_Classeur_Fichier cf
        INNER JOIN Fichiers f ON f.id = cf.id_fichier
        WHERE c.id = cf.id_classeur
            AND f.name like '%top secret%'
    )
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  13. #13
    Membre régulier
    Inscrit en
    Juin 2008
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 99
    Points : 74
    Points
    74
    Par défaut
    Salut,

    Merci cinePhil pour l'exemple.
    J'ai testé, ça marche tout pareil, avec un temps d'exécution de requête identique.
    Je mets tout ça dans une note en espérant la retrouver la prochaine fois !!! (Au pire je retomberai peut être sur le topic, le plus dûr étant de trouver les mots clefs !)

    Merci à tous pour votre aide efficace !!!

    Bon week-end.

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

Discussions similaires

  1. [MySQL-5.1] Besoin d'aide sur une erreur de requête
    Par bpdelavega dans le forum Requêtes
    Réponses: 8
    Dernier message: 20/11/2013, 15h39
  2. Aide sur une demande de requête au niveau de SQL Server
    Par Msysteme dans le forum Langage SQL
    Réponses: 1
    Dernier message: 08/04/2013, 23h01
  3. Besoin d'aide sur une requête (JOIN + COUNT ?)
    Par PanzerKunst dans le forum Langage SQL
    Réponses: 2
    Dernier message: 01/06/2005, 10h29
  4. Aide sur une requête
    Par TshAw dans le forum Langage SQL
    Réponses: 4
    Dernier message: 28/02/2005, 11h42
  5. Aide sur une requête (Group By...??)
    Par Cocolapin dans le forum Langage SQL
    Réponses: 4
    Dernier message: 12/12/2004, 10h26

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