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 avec inner join incorrect


Sujet :

Langage SQL

  1. #1
    Candidat au Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Novembre 2014
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Novembre 2014
    Messages : 4
    Points : 3
    Points
    3
    Par défaut Requête SQL avec inner join incorrect
    Bonjour !

    J'ai un problème avec une requete que j'essaie de faire afficher (sous windev, pour la précision).

    Pour le contexte, j'ai des demandes, chaque demandes a 2signatures qui sont d'un types différent (on les appellera 1 et 2, ça tombe bien, c'est le numéro de leurs ID ), et chaque signature peut être accordé ou non.

    Donc j'ai une table demande, ou sont la plupart des informations de la demande, une table demande_signature, ou j'ai deux lignes pour chaque demande, avec l'id de la demande, l'id de la signature (1ou2), et accord qui est à 0 ou 1. Enfin une table signature, ou il y a donc deux types.

    Je voudrais pouvoir trier ces enregistrements notamment si elles possèdent une signature accordé ou non. Par exemple, ceux dont la signature 1 est accordé, et la signature 2 n'est pas accordés.

    Pour le moment, j'ai ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT  * 
    FROM DEMANDE  
    LEFT JOIN Signature_Demande on Demande.IDDemande = Signature_Demande.IDDemande  
    WHERE  (Signature_Demande.IDSignature = 2 AND Signature_Demande.Accord=0)
    AND (Signature_Demande.IDSignature = 1 AND Signature_Demande.Accord=1)
    Bon en réalité j'ai simplifié car j'ai d'autre trie et je ne choisis pas tout dans demande, mais c'est a peu près ça.

    Et ce code ne fonctionne pas, je pense que c'est parce que je demande a Signature_Demande.IDSignature d'être en même temps égale a 1 et a 0 (pour accord aussi). Néanmoins, je ne vois pas comment faire pour trouver une autre solution.

    Une idée ?

    Merci d'avance !

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 386
    Points
    18 386
    Par défaut
    Citation Envoyé par FabienLep Voir le message
    Et ce code ne fonctionne pas, je pense que c'est parce que je demande a Signature_Demande.IDSignature d'être en même temps égale a 1 et a 0 (pour accord aussi).
    Effectivement cette analyse est la bonne.
    J'ai lu en diagonale votre besoin, mais essayez de simplement changer le AND du début de la ligne 5 par un OR.

  3. #3
    Candidat au Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Novembre 2014
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Novembre 2014
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Malheureusement cela ne fonctionne pas. En effet j'ai besoin de récupérer ceux dont la signature 1 est accordé ET la signature 2 refusé.
    Votre solution affiche également ceux dont les deux sont accordé/refusé.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 243
    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 243
    Points : 12 874
    Points
    12 874
    Par défaut
    Bonjour,
    Comme il y a un test dans la clause WHERE sur une colonne de la table Signature_Demande , la jointure externe se "transforme" en jointure interne.
    Il faut déplacer ces test dans la condition de jointure.

    Tatayo.

  5. #5
    Candidat au Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Novembre 2014
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Novembre 2014
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Heuuu, oui peut être, enfin j'ai un peu de mal à voir ce que je dois faire exactement.
    Je pense qu'il faut que je mette ma condition juste après le INNER JOIN, mais je pourrais avoir un exemple que je comprenne un peu mieux ? Cette notion est un peu flou pour moi je dois dire !

  6. #6
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 950
    Points : 5 849
    Points
    5 849

  7. #7
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 102
    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 102
    Points : 31 544
    Points
    31 544
    Billets dans le blog
    16
    Par défaut
    Bonsoir,



    Citation Envoyé par FabienLep Voir le message
    j'ai besoin de récupérer ceux dont la signature 1 est accordé ET la signature 2 refusé
    Ceci devrait convenir :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT DISTINCT IdDemande 
    FROM   DEMANDE AS x
    WHERE  IdSigature = 1 AND Accord = 'accordé' 
      AND  EXISTS (SELECT '' 
                   FROM   DEMANDE AS y
                   WHERE  x.IdDemande = y.IdDemande 
                     AND  y.IdSignature = 2 AND y.Accord = 'refusé') ;


    Version jointure :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT DISTINCT x.IdDemande
    FROM   DEMANDE AS x INNER JOIN DEMANDE AS y ON x.IdDemande = y.IdDemande
    WHERE  x.IdSignature = 1 AND x.Accord = 'accordé'
     AND   y.IdSignature = 2 AND y.Accord = 'refusé' ;


    Edit du 10/11/2014

    Ce que j’ai proposé ne traite en fait que de la partie table DEMANDE_SIGNATURE, ce doit donc être lu ainsi :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT DISTINCT IdDemande 
    FROM   DEMANDE_SIGNATURE AS x
    WHERE  IdSigature = 1 AND Accord = 'accordé' 
      AND  EXISTS (SELECT '' 
                   FROM   DEMANDE_SIGNATURE AS y
                   WHERE  x.IdDemande = y.IdDemande 
                     AND  y.IdSignature = 2 AND y.Accord = 'refusé') ;


    Version jointure :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT DISTINCT x.IdDemande
    FROM   DEMANDE_SIGNATURE AS x INNER JOIN DEMANDE_SIGNATURE AS y ON x.IdDemande = y.IdDemande
    WHERE  x.IdSignature = 1 AND x.Accord = 'accordé'
     AND   y.IdSignature = 2 AND y.Accord = 'refusé' ;

    Pour la version prenant aussi en compte la table DEMANDE, voir mon message suivant.

  8. #8
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 103
    Points : 9 499
    Points
    9 499
    Par défaut
    Pour une ligne de la table demande , vous avez besoin d'aller chercher 2 enregistrements distincts dans la table signature_demande.

    Pour 1 ligne de la vue 'résultat', il y aura donc des infos qui viennent de 3 tables différentes.

    La requête sera donc de la forme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select * from demande d , signature_demande sd1, signature_demande sd2    where ....
    ou encore :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select * from demande
      left_join signature_demande sd1  on ...
      left_join signature_demande sd2  on ...

    Reste un point qui n'est pas clairement décrit dans le message initial.
    Est-ce que pour une id_demande donnée, on est sûr de trouver les 2 enregistrements dans signature_demande ...avec 0 ou 1 dans la colonne accord, ou bien il peut y avoir des lignes manquantes ?
    Parce que j'ai l'impression qu'on n'est pas du tout dans un contexte d'INNER JOIN, mais de jointure classique.

  9. #9
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 102
    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 102
    Points : 31 544
    Points
    31 544
    Billets dans le blog
    16
    Par défaut
    Bonsoir,


    Dans mon précédent message, je m’étais cantonné à la seule table DEMANDE_SIGNATURE. Si la table DEMANDE participe, on peut enrichir ainsi (où le mot "INNER" est facultatif) :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT x.*
    FROM   DEMANDE AS x INNER JOIN DEMANDE_SIGNATURE AS y ON x.IdDemande = y.IdDemande 
                        INNER JOIN DEMANDE_SIGNATURE AS z ON x.IdDemande = z.IdDemande
    WHERE  y.IdSignature = 1 AND y.Accord = 'accordé'
     AND   z.IdSignature = 2 AND z.Accord = 'refusé'  
     ;

    Une variante parmi d’autres :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT x.* 
    FROM   DEMANDE AS x JOIN DEMANDE_SIGNATURE AS y USING (IdDemande)
                        JOIN DEMANDE_SIGNATURE AS z USING (IdDemande) 
    WHERE  y.IdSignature = 1 AND y.Accord = 'accordé'
     AND   z.IdSignature = 2 AND z.Accord = 'refusé'  
     ;




    Citation Envoyé par tbc92 Voir le message
    ou encore :
    select * from demande
    left_join signature_demande sd1 on ...
    left_join signature_demande sd2 on ...
    Dans la mesure où Fabien a besoin de récupérer uniquement les demandes pour lesquelles la signature 1 est accordée et la signature 2 refusée, je ne vois pas bien l’intérêt d’un LEFT JOIN (qui ouvre la porte à Null qui plus est).


    Citation Envoyé par tbc92 Voir le message
    J'ai l'impression qu'on n'est pas du tout dans un contexte d'INNER JOIN, mais de jointure classique.
    Qu’appelez-vous « jointure classique » ?

  10. #10
    Candidat au Club
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Novembre 2014
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Novembre 2014
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Bonjour !

    Merci beaucoup, ça fonctionne parfaitement ! La réalité, c'est que je n'avais aucune idée que l'on pouvais faire plusieurs inner join sur une même table, ça semble évident maintenant !

    Et pour information, il est effectivement obligatoire pour chaque demande d'avoir 2 signature exactement dans la base.

    Bonne journée !

  11. #11
    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,

    Citation Envoyé par FabienLep Voir le message
    Merci beaucoup, ça fonctionne parfaitement ! La réalité, c'est que je n'avais aucune idée que l'on pouvais faire plusieurs inner join sur une même table, ça semble évident maintenant !
    On peut aussi faire avec une seule jointure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT x.IdDemande
    FROM   DEMANDE AS x 
    INNER JOIN DEMANDE_SIGNATURE AS y 
        ON x.IdDemande = y.IdDemande 
    GROUP BY x.IdDemande
    HAVING MAX( CASE WHEN y.IdSignature = 1 THEN y.Accord END ) = 'accordé'
     AND   MAX( CASE WHEN y.IdSignature = 2 THEN y.Accord END ) = 'refusé'

  12. #12
    Rédacteur/Modérateur

    Homme Profil pro
    Ingénieur qualité méthodes
    Inscrit en
    Décembre 2013
    Messages
    4 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur qualité méthodes
    Secteur : Conseil

    Informations forums :
    Inscription : Décembre 2013
    Messages : 4 103
    Points : 9 499
    Points
    9 499
    Par défaut
    Citation Envoyé par fsmrel Voir le message
    Bonsoir,


    Qu’appelez-vous « jointure classique » ?

    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select d.* 
    from demande d, signature_demande sd1, signature_demande sd2
    where sd1.id_demande = d.id_demande  and sd1.id_signature = 1 and sd1.accord = 1
    and    sd2.id_demande = d.id_demande  and sd2.id_signature = 1 and sd2.accord = 0

  13. #13
    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
    Les jointures s'écrivent depuis plus de 20 ans avec l'opérateur JOIN. Il serait temps de s'y mettre !

  14. #14
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 102
    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 102
    Points : 31 544
    Points
    31 544
    Billets dans le blog
    16
    Par défaut Les Anciens et les Modernes
    Bonjour,


    Citation Envoyé par tbc92 Voir le message
    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select d.* 
    from demande d, signature_demande sd1, signature_demande sd2
    where sd1.id_demande = d.id_demande  and sd1.id_signature = 1 and sd1.accord = 1
    and    sd2.id_demande = d.id_demande  and sd2.id_signature = 1 and sd2.accord = 0
    D’accord. Comme l’écrit dans SQL and Relational Theory (pages 114, 115), celui qui est la référence en matière de relationnel, C. J. Date :

    FROM t1 JOIN t2 ON bx

    Est logiquement équivalent à

    FROM t1, t2 WHERE bx

    (Où bx est une expression booléenne représentant une condition de jointure).

    Chacun est donc libre d’utiliser le style qu’il trouve à son goût, sans que quiconque trouve à y redire. Dans les deux cas, l’optimiseur d’un SGBDR digne de ce nom doit produire très exactement le même plan d’application.


    Cela dit, chez DVP l’usage est d’utiliser le style « moderne », plus lisible, même si logiquement parlant c’est bonnet blanc et blanc bonnet. Bien que dinosaure ès bases de données, je m'y suis mis sans problème, ce qui n’empêche pas que dans mes échanges avec Date je conserve l'ancien style.




    Citation Envoyé par CinePhil Voir le message
    Les jointures s'écrivent depuis plus de 20 ans avec l'opérateur JOIN. Il serait temps de s'y mettre !
    Des goûts et des couleurs : comme je viens de l’écrire, à chacun sa préférence.

    1) Dans l’ouvrage cité ci-dessus, Date recommande tant qu’à faire d’utiliser NATURAL JOIN.

    2) Pour ceux que ça peut intéresser, un bref rappel historique :

    La version « classique » évoquée par tbc92 date de 1974, voyez l’article des pères de SQL, Boyce et Chamberlin (lesquels sont bien sûr partis des travaux de Codd) : SEQUEL: A structured English Query Language :

    Q10. List rows of SALES and SUPPLY concatenated together whenever their ITEM values match.

    SALES, SUPPLY
    WHERE SALES. ITEM = SUPPLY.ITEM

    La version moderne de la jointure (INNER JOIN, OUTER JOIN) date de 1983 (C. J. Date, The Outer Join. The 2nd International Conference on Databases. Cambridge, England. 1983. pp. 76-106). Date a repris son article en 1986 dans Relational Database Selected Writings “The Outer Join” ⁽¹⁾.

    Syntaxe proposée par Date à cette époque :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     join-expression
        ::=  [ OUTER | INNER ] JOIN  relation-commalist on-clause
    Comme je ‘ai déjà signalé dans certaines discussions chez DVP :

    Dans Relational Databases, Writings 1989-1991 ⁽²⁾, paru en 1992, C. J. Date écrivit par ailleurs (au chapitre 19, Watch Out for Outer Join, initialement publié dans InfoDB 5, No. 1 (Spring/Summer 1990)) :

    I am glad to see that the SQL standards committees are in fact planning such an extension in their proposed follow-on to the existing SQL standard known as SQL2.

    Les éditeurs de SGBD ont pris plus ou moins leur temps avant de proposer la construction INNER | OUTER JOIN. Par exemple, IBM ne l’a fait qu’en 1995, avec la version 4 de DB2 for MVS/ESA (autant dire en 1998 pour nous, pauvres utilisateurs, toujours en retard d’une version, contexte de production, plans de tests, de régression, etc. obligent). A la décharge d’IBM, la V3 de DB2 avait été livrée en 1993, et il n’était évidemment pas possible de la chambouler, d’envoyer au pilon des wagons de documentation prêts depuis un an, tout cela parce qu’en même temps naquit SQL/2.

    Quant à ORACLE, il a fallu attendre 2002 (Oracle 9i) pour qu’il se mette à la norme.

    Pour MySQL : je suis pas compétent pour répondre, mais vu sa date de naissance (1995 si j’en crois Wikipédia), il a sans doute dû prendre en compte la norme dès le départ.

    Pour SQL Server : voyez SQLpro...

    Etc.

    P.-S. Attention les Anciens ! CinePhil va sortir sa sulfateuse, planquons-nous !

    ______________________
    ⁽¹⁾ Ouvrage (ISBN 0201141965) que l’on peut acquérir pour environ 10 euros (port compris), par exemple chez AbeBooks.

    ⁽²⁾ Ouvrage (ISBN 0201543036) que l’on aussi acquérir pour environ 10 euros (port compris), toujours chez AbeBooks

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

Discussions similaires

  1. Requête SQL avec inner join, pas certaine de ma requête
    Par marieSQL dans le forum Requêtes
    Réponses: 1
    Dernier message: 15/03/2015, 23h08
  2. Requête update avec inner join
    Par mattmax dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 23/05/2013, 14h53
  3. [AC-2003] Resultat de requête SQL avec des dates incorrect
    Par rockin-bones dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 19/05/2011, 14h35
  4. [Access] Problème dans une requête SQL avec INNER JOIN ?
    Par bds2006 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 27/06/2006, 10h57
  5. requête sql avec clause INNER JOIN
    Par new_wave dans le forum Langage SQL
    Réponses: 1
    Dernier message: 12/08/2005, 15h47

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