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 sql, lien entre table


Sujet :

Langage SQL

  1. #1
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 17
    Points : 9
    Points
    9
    Par défaut requête sql, lien entre table
    Bonjour,

    Pour commencer je vais essayer de vous decrire avec precision mon problème.
    J'ai deux tables :
    PRODUIT qui contient ID_PRODUIT, DESIGNATION etc ...
    CONTROLE qui contient ID_CONTROLE, ID_PRODUIT, TYPE etc ...

    Et j'aimerai recupérer dans une seule requête toute les données de CONTROLE plus le champ DESIGNATION de PRODUIT ainsi j'ai cette requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select a.ID_CONTROLE, a.ID_PRODUIT, a.TYPE, b.DESIGNATION 
    from CONTROLE a, PRODUIT b 
    where a.ID_PRODUIT = b.ID_PRODUIT
    Le problème est que l'ID_PRODUIT d'un CONTROLE peut etre null ou ne pas etre dans la table PRODUIT, de ce fait, si un CONTROLE et lié à un PRODUIT, son TYPE sera 'S' sinon c'est 'A' (comme Autre), et j'aimerai connaitre la requête qui m'affiche les CONTROLE et son champ DESIGNATION ainsi que les CONTROLE n'etant pas relié à un PRODUIT.
    En premier lieu j'ai pensé que la requête : "select a.ID_CONTROLE, a.ID_PRODUIT, a.TYPE, b.DESIGNATION from CONTROLE a, PRODUIT b where a.ID_PRODUIT = b.ID_PRODUIT and a.TYPE='A' " pourrait repondre à ma question mais au lieu de ça elle m'affiche la ligne d'un CONTROLE de TYPE 'A' autant de fois que de DESIGNATION dans ma table PRODUIT.

    Exemple :
    Il m'affiche
    ID_CONTROLE ID_PRODUIT TYPE DESIGNATION
    1 NULL A designation1
    1 NULL A designation2
    1 NULL A designation3
    2 NULL A designation1
    2 NULL A designation2
    2 NULL A designation3

    Au lieu de
    ID_CONTROLE ID_PRODUIT TYPE DESIGNATION
    1 NULL A NULL
    2 NULL A NULL

    Si vous arrivez à m'aider je vous en serait déjà très reconnaissant mais ce n'est pas tout

    En effet j'aimerai aussi qu'il ne m'affiche qu'un seul CONTROLE par ID_PRODUIT.

    Par exemple si j'ai dans ma table CONTROLE :
    ID_CONTROLE ID_PRODUIT TYPE
    1 1 S
    2 1 S
    3 1 S
    4 2 S
    5 2 S
    6 3 S

    Je voudrai qu'il m'affiche :
    ID_CONTROLE ID_PRODUIT TYPE DESIGNATION
    1 1 A designation1
    4 2 A designation2
    6 3 A designation3

    Voila j'espère avoir été assez clair et j'espère vraiment avoir une aide de votre part.
    Merci d'avance.

    Gaëtan.

  2. #2
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 17
    Points : 9
    Points
    9
    Par défaut
    Pour ma deuxième demande, j'ai trouvé la solution, il suffit de faire un distinct :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    select distinct ID_PRODUIT ID_CONTROLE,ID_PRODUIT,TYPE 
    from CONTROLE
    Par contre je n'ai toujours pas d'idée pour ma première demande donc votre aide est la bienvenue.

    Gaëtan.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    861
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 861
    Points : 965
    Points
    965
    Par défaut
    Bonjour,

    Essayez de prendre l'habitude d'utiliser la syntaxe normalisée pour vos jointures :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT 
           a.ID_CONTROLE, 
           a.ID_PRODUIT, 
           a.TYPE, 
           b.DESIGNATION 
    FROM CONTROLE a
    INNER JOIN PRODUIT b ON a.ID_PRODUIT = b.ID_PRODUIT
    Pour ramener également les contrôles qui n'ont pas de correspondance dans les produits, utilisez une jointure externe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT 
           a.ID_CONTROLE, 
           a.ID_PRODUIT, 
           a.TYPE, 
           b.DESIGNATION 
    FROM CONTROLE a
    LEFT OUTER JOIN PRODUIT b ON a.ID_PRODUIT = b.ID_PRODUIT
    Pour info, les mots clé OUTER et INNER sont facultatifs sur la plupart des SGBD.

    Aussi, je doute que DISTINCT règle votre second problème tel que vous nous l'avez décrit, étant donné que les lignes ne sont pas distinctes. Si vous ne voulez conserver qu'un seul contrôle par produit, il faudra définir une règle pour choisir le contrôle à afficher, par exemple le plus récent, ou l'ID le plus élevé.

    EDIT :
    En premier lieu j'ai pensé que la requête : "select a.ID_CONTROLE, a.ID_PRODUIT, a.TYPE, b.DESIGNATION from CONTROLE a, PRODUIT b where a.ID_PRODUIT = b.ID_PRODUIT and a.TYPE='A' " pourrait repondre à ma question mais au lieu de ça elle m'affiche la ligne d'un CONTROLE de TYPE 'A' autant de fois que de DESIGNATION dans ma table PRODUIT.
    Vous semblez confondre AND et OR. Ici, ça aurait pu marcher avec OR : ramener les ligne de la requête où (a.ID_PRODUIT = b.ID_PRODUIT OU a.TYPE='A').

  4. #4
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 17
    Points : 9
    Points
    9
    Par défaut
    Merci pour vos réponses qui m'on déjà permis de bien avancé.
    Je ne connaissais pas cette synthaxe de jointure et je vous remercie de m'en informer.

    Par contre pour votre réponse à mon second problème je ne vois pas comment m'y prendre. En effet j'aimerai qu'il m'affiche le controle ayant le plus petit ID pour chaque produit. Pour ceci doit-je encore faire une jointure ?

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    861
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 861
    Points : 965
    Points
    965
    Par défaut
    Il faut faire une sous-requête qui vous ramènera les couples id_controle/id_produit qui vous interessent, c'est à dire min(id_controle) groupé par id_produit.
    Par contre, si vous voulez tous les contrôles qui n'ont pas de correspondance dans les produits, il faut également gérer ce cas en utilisant à nouveau une jointure externe et en ajoutant des conditions dans le where.
    Vous pouvez essayer ceci :
    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
     
    SELECT 
           a.ID_CONTROLE, 
           a.ID_PRODUIT, 
           a.TYPE, 
           b.DESIGNATION 
    FROM CONTROLE a
    LEFT OUTER JOIN
         (
          SELECT min(id_controle) AS id_controle, id_produit
          FROM CONTROLE
          WHERE id_produit IS NOT NULL
          GROUP BY id_produit
         ) c_min 
         ON a.id_controle = c_min.id_controle
         AND a.id_produit = c_min.id_produit
    LEFT OUTER JOIN PRODUIT b 
         ON a.ID_PRODUIT = b.ID_PRODUIT
    WHERE (c_min.id_produit IS NOT NULL 
    OR a.id_produit IS NULL)

  6. #6
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 17
    Points : 9
    Points
    9
    Par défaut
    Merci pour votre réponse. J'ai regarder cela de mon côté et j'ai abouti à cette requête qui (il me semble) fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    SELECT
    	a.ID_CONTROLE, 
           a.ID_PRODUIT, 
           a.TYPE, 
           b.DESIGNATION 
    FROM CONTROLE a
    LEFT OUTER JOIN PRODUIT b ON a.ID_PRODUIT = b.ID_PRODUIT
    JOIN 
    (SELECT ID_PRODUIT ,MAX(ID_CONTROLE) AS ID_CONTROLE 
     FROM CONTROLE GROUP BY ID_PRODUIT)TD 
    ON a.ID_CONTROLE = TD.ID_CONTROLE
    En tout cas je vous remercie d'avoir pris le temps de m'aider. Je vais maintenant pouvoir continuer la programmation de mon application.

    Gaëtan.

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    861
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 861
    Points : 965
    Points
    965
    Par défaut
    Avec cette requête, à priori vous ne récupérerez qu'un seul contrôle parmi ceux qui n'ont pas de produit associé.

  8. #8
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 17
    Points : 9
    Points
    9
    Par défaut
    Oui mais en faite maintenant les ID_PRODUIT de la table CONTROLE ne seront jamais NULL, il porteront un ID_PRODUIT qui n'est pas referencé dans la table PRODUIT. Ainsi il m'affiche bien tout les champs voulu. Prevenez moi si je me trompe

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    861
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 861
    Points : 965
    Points
    965
    Par défaut
    S'ils ne sont pas null mais ont tous une même valeur que ne peut pas prendre l'id des produits, par exemple -1, ça formera un groupe et vous ne récupèrerez que celui qui a le plus petit ID parmi tous ces contrôles.

  10. #10
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 17
    Points : 9
    Points
    9
    Par défaut
    Oui c'est ce que je souhaite car j'ai maintenant une autre page qui m'affiche tout les CONTROLES associé quand je suis sur une donnée de la requête demandé.

  11. #11
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 17
    Points : 9
    Points
    9
    Par défaut
    Bonjour,
    Me revoila pour un nouveau problème que je n'arrive pas à résoudre tout seul, je reclame donc (encore) de l'aide de votre part.

    Cette question concerne toujours la même requête. J'aimerai qu'en plus des resultat qu'elle m'affiche déjà, qu'elle me donne le nombre de CONTROLE pour chaque PRODUIT.

    En gros j'aimerai integré la requête suivante dans celle déjà existante que vous m'avez aidé à trouver :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT 
    COUNT(*) AS NB_CONTROLE FROM CONTROLE
    WHERE ID_PRODUIT = (l'id du produit actuel vu que ma requete affiche le premier CONTROLE de chaque PRODUIT)
    J'espère avoir été assez claire et que vous pourriez m'aider de nouveau.

    Merci,
    Gaëtan.

  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 : 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
    Pas tout lu en détail mais il suffit je pense d'ajouter le COUNT(*) dans la sous-requête et de sélectionner ce résultat dans le SELECT général :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT a.ID_CONTROLE, a.ID_PRODUIT, a.TYPE, 
      b.DESIGNATION,
      TD.nb_controles
    FROM CONTROLE a
    LEFT OUTER JOIN PRODUIT b ON a.ID_PRODUIT = b.ID_PRODUIT
    INNER JOIN (
      SELECT ID_PRODUIT, 
        MAX(ID_CONTROLE) AS ID_CONTROLE,
        COUNT(*) As nb_controles
      FROM CONTROLE 
      GROUP BY ID_PRODUIT
    ) TD ON a.ID_CONTROLE = TD.ID_CONTROLE
    À tester.

  13. #13
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 17
    Points : 9
    Points
    9
    Par défaut
    Nikel, sa fonctionne !
    Merci encore !

  14. #14
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 17
    Points : 9
    Points
    9
    Par défaut
    J'ai encore une petite question ... Je commence à croire que le sql n'est pas fait pour moi

    Tout d'abord je veux récupérer les données d'un CONTROLE avec une donnée d'un PRODUIT, j'obtient donc cette requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select a.ID_PRODUIT,a.COTE,a.DATE,b.DESIGNATION,a.POURCENTAGE,a.CONFORME
    from CONTROLE a, PRODUIT b
    where a.ID_PRODUIT = b.ID_PRODUIT
    J'ai envie de dire normal, mais à partir de là j'aimerai qu'il ne m'affiche pas les CONTROLE ayant le même ID_PRODUIT et COTE (les deux ensemble) pour ne pas afficher les doublons.

    Pour être plus claire imaginons que j'ai ceci :
    ID_PRODUIT COTE POURCENTAGE DATE ...
    1 cote1 33,4 01/01/2010
    1 cote1 21,2 02/01/2010
    1 cote2 2,5 03/01/2010
    2 cote1 6,8 01/01/2010
    2 cote1 5,1 01/02/2010
    J'aimerai qu'il m'affiche :
    ID_PRODUIT COTE POURCENTAGE DATE ...
    1 cote1 21,2 02/01/2010
    1 cote2 2,5 03/01/2010
    2 cote1 5,1 01/02/2010
    Car les CONTROLES ayant le même ID_PRODUIT et COTE sont des CONTROLES identique mais fait à des moments differents (c'est une sorte d'historique) et je voudrai qu'il ne m'affiche que le dernier CONTROLE en date.

    J'ai donc tout d'abord pensé au DISTINCT puis au GROUP BY j'en suis donc arrivé à cette requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select
    a.ID_PRODUIT,a.COTE,a.DATE,b.DESIGNATION,a.POURCENTAGE,a.CONFORME
    from CONTROLE a, PRODUIT b
    where a.ID_PRODUIT = b.ID_PRODUIT And a.ID_PRODUIT,a.COTE IN 
    (select distinct ID_PRODUIT,COTE from CONTROLE)
    Le problème est qu'il ne veux pas me faire un IN sur deux champs (ID_PRODUIT et COTE), avez vous une idée pour solutionner mon problème ?

  15. #15
    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
    Quand un problème est trop complexe pour être apréhendé dans sa globalité, il faut le décomposer en problèmes plus simples.
    Je crois qu'un certain Descartes a dit à peu près la même chose il y a quelques siècles dans sont Discours de la Méthode.

    je voudrai qu'il ne m'affiche que le dernier CONTROLE en date
    La requête simple qui va donner ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT ID_PRODUIT, COTE, MAX(DATE) AS Date_Max
    FROM CONTROLE
    GROUP BY ID_PRODUIT, COTE
    Pour récupérer les autres informations souhaitées, on fait une jointure avec cette requête et on restreint le contrôle à celui correspondant à la Date_Max
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT p.ID_PRODUIT, c.COTE, c.DATE, p.DESIGNATION, c.POURCENTAGE, c.CONFORME
    FROM PRODUIT p
    INNER JOIN CONTROLE c ON c.ID_PRODUIT = c.ID_PRODUIT
    INNER JOIN (
      SELECT ID_PRODUIT, COTE, MAX(DATE) AS Date_Max
      FROM CONTROLE
      GROUP BY ID_PRODUIT, COTE
    ) t ON t.ID_PRODUIT = p.ID_PRODUIT
    WHERE c.DATE = t.Date_Max
    Au passage, c'est une mauvaise idée d'appeler une colonne 'DATE' parce que c'est un mot réservé du langage SQL.

  16. #16
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 17
    Points : 9
    Points
    9
    Par défaut
    Impeccable sa fonctionne

    J'aime de plus en plus ce forum et les membres qui en font partie

    Il y avait juste un problème qui vennait de moi : si deux CONTROLE été fait à la même date il était affiché tout les deux même si il avait le même ID_PRODUIT et COTE, j'ai donc fait la selection à partir de l'ID du CONTROLE (le plus grand id est le plus recent).

    Bref, je vous remercie pour la énième fois.

    PS : Pour le nom du champ DATE ce n'est pas le veritable nom que je lui ai donné tout comme les autres nom de champ ou table, ceci pour aider à la compréhension, je retraduit ensuite

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

Discussions similaires

  1. [AC-2007] Lien entre tables et requêtes access
    Par mathmath99 dans le forum Requêtes et SQL.
    Réponses: 7
    Dernier message: 25/01/2013, 17h44
  2. Requête et liens entre tables MySQL
    Par kaking dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 09/11/2008, 09h23
  3. Lien entre tables lors d'une requête
    Par thom30 dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 10/12/2007, 15h49
  4. Pb de liens entre table pour une requête
    Par syldudu dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 31/08/2006, 17h27
  5. A propos d'une requête SQL sur plusieurs tables...
    Par ylebihan dans le forum Langage SQL
    Réponses: 2
    Dernier message: 14/09/2003, 16h26

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