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 :

Jointure, au pire sur une valeur par défaut


Sujet :

Langage SQL

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    30
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Octobre 2013
    Messages : 30
    Points : 26
    Points
    26
    Par défaut Jointure, au pire sur une valeur par défaut
    Bonjour,

    Je poste ici car aprés quelques heures sur Google, je reste bloqué.
    Jusqu'ici on m'a conseillé de changer la structure de ma base...ce qui auraient quelques conséquences (lourdes)

    Voici mon problème simplifié (en pratique j'ai plus de champs, une tableC en union avec la tableB, des tableD et E qui cascadent sans avoir la même problématique)

    J'ai une tableA

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    monType Path :
    ---------------
    all          ibidem
    Spe1      ibidem
    Spe2      ibidem

    Ainsi qu'une tableB :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Path     monType
    ---------------
    ibidem   all
    ibidem   Spe1
    Ce que j'aimerais (textuel) : faire une jointure de tableA et tableB sur (tableA.Path = tableB.Path) AND (tableA.monType = tableB.monType si possible, sinon tableA.monType = 'all')
    Ce que j'aimerais (résultat) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    tableA.monType Path tableB.monType
    -------------------------------------
    all                   ibidem   all
    Spe1               ibidem   Spe1
    Spe2               ibidem   all (car je n'ai pas de Spe2 à joindre)

    Problème : Je n'arrive pas à poser la bonne question sur google (perdu entre les JOIN/AND/CASE, les WHERE/CASE et autres COALESCE)

    Au mieux j'arrive à m'en tirer avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    tableA.monType Path tableB.monType
    -------------------------------------
    all                   ibidem   all
    Spe1               ibidem   Spe1
    Spe1               ibidem   all (semi doublon qui ne me va pas)
    Spe2               ibidem   all
    Je cherche :
    1 - La réponse : quelle requete utiliser ?
    2 - Des éléments de réponses
    3 - Des pistes pour continuer de torturer Big G afin de trouver mes réponses.


    Limitation : SQLite3.


    Merci d'avance,
    K.

  2. #2
    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
    Par défaut
    Je ne sais pas si je comprends très bien le besoin, l'exemple est probablement trop simpliste.
    En l'état, il suffit de faire une jointure externe puis de remplacer NULL par all s'il n'y a pas de correspondance de la table A dans la table B :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select ta.montype, ta.path, coalesce(tb.montype,'all')
      from ta
      left join tb 
        on tb.path = ta.path
       and tb.montype = ta.montype

  3. #3
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 115
    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 115
    Points : 28 493
    Points
    28 493
    Par défaut
    La première solution qui me vient à l'esprit est de passer par une UNION :
    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  tga.*, tbb.*
    FROM    tableA  tba
        INNER JOIN
            tableB  tbb
            ON  tba.Path    = tbb.Path
            AND tba.monType = tbb.monType
    UNION
    SELECT  tga.*, tbb.*
    FROM    tableA  tba
        INNER JOIN
            tableB  tbb
            ON  tba.Path    = tbb.Path
    WHERE   tba.monType = 'all'
        AND NOT EXISTS
            (   SELECT  NULL
                FROM    tableA  tba
                WHERE   tba.Path    = tbb.Path
                    AND tba.monType = tbb.monType
            )
    ;

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    30
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Octobre 2013
    Messages : 30
    Points : 26
    Points
    26
    Par défaut
    Citation Envoyé par skuatamad Voir le message
    Je ne sais pas si je comprends très bien le besoin, l'exemple est probablement trop simpliste.
    En l'état, il suffit de faire une jointure externe puis de remplacer NULL par all s'il n'y a pas de correspondance de la table A dans la table B :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select ta.montype, ta.path, coalesce(tb.montype,'all')
      from ta
      left join tb 
        on tb.path = ta.path
       and tb.montype = ta.montype
    Merci pour la rapidité, je viens de tester.

    Le problème ici c'st que le left join avec les 2 conditions permet d'obtenir (en gardant la même syntaxe que dans le post initial):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    tableA.monType Path tableB.monType
    -------------------------------------
    all ibidem all
    Spe1 ibidem Spe1
    Et non

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    tableA.monType Path tableB.monType
    -------------------------------------
    all ibidem all
    Spe1 ibidem Spe1
    Spe2 ibidem all (car je n'ai pas de Spe2 à joindre)
    ...possible qu'il y ait un soucis pour le left join dans mon gestionnaire sqlite.

    Pour préciser, il n'est pas juste question de mettre une valeur à all mais bien de joindre selon les monType (Spe1 sur Spe1, all sur all) et d'utiliser une valeur par defaut (Spe2 sur all en l'absence de Spe2 sur Spe2).

    Je continue mes recherches (et la lecture du second post de réponse)

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    30
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Octobre 2013
    Messages : 30
    Points : 26
    Points
    26
    Par défaut
    Citation Envoyé par al1_24 Voir le message
    La première solution qui me vient à l'esprit est de passer par une UNION :
    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  tga.*, tbb.*
    FROM    tableA  tba
        INNER JOIN
            tableB  tbb
            ON  tba.Path    = tbb.Path
            AND tba.monType = tbb.monType
    UNION
    SELECT  tga.*, tbb.*
    FROM    tableA  tba
        INNER JOIN
            tableB  tbb
            ON  tba.Path    = tbb.Path
    WHERE   tba.monType = 'all'
        AND NOT EXISTS
            (   SELECT  NULL
                FROM    tableA  tba
                WHERE   tba.Path    = tbb.Path
                    AND tba.monType = tbb.monType
            )
    ;

    Dans la logique quelque chose dans ce gout là.
    Prendre avec le inner join sur 2 conditions (le restrictif) puis ajouter ceux du inner join avec 1 condition qui sont 'all' dans la tableB et qui n'existent pas dans le premier inner join (restrictif).

    Je sens que c'est pas la version élégante mais je vais essayer de faire tourner cette requete, merci.

  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
    Bonjour,

    Vous pouvez aussi essayer ceci (un peu moche, mais ça devrait fonctionner)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    SELECT 
    		A.monType
    		,A.Path
    		,C.MonType
    		,C.Path
    FROM TableA A
    LEFT JOIN TableB B
    	ON		B.Path = A.Path
    	AND		B.monType = A.monType
    LEFT JOIN TableB C
    	ON		C.Path = A.Path
    	AND		C.monType = COALESCE(B.monType, 'all')

  7. #7
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 115
    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 115
    Points : 28 493
    Points
    28 493
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    un peu moche, mais ça devrait fonctionner
    Je trouve au contraire cela très élégant comme solution.

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2013
    Messages
    30
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Octobre 2013
    Messages : 30
    Points : 26
    Points
    26
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Bonjour,

    Vous pouvez aussi essayer ceci (un peu moche, mais ça devrait fonctionner)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    SELECT 
    		A.monType
    		,A.Path
    		,C.MonType
    		,C.Path
    FROM TableA A
    LEFT JOIN TableB B
    	ON		B.Path = A.Path
    	AND		B.monType = A.monType
    LEFT JOIN TableB C
    	ON		C.Path = A.Path
    	AND		C.monType = COALESCE(B.monType, 'all')
    J'étais dubitatif avec le second left join mais aprés test ça passe.

    Si je SELECT *, j'ai bien des colonnes qui ne me serviront pas mais..it's works !

    Merci à toi et à tous,
    Je vais adapter ça sur le cas concret.

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 31/10/2014, 13h06
  2. Réponses: 5
    Dernier message: 01/02/2013, 14h19
  3. [PEAR][HTML_QuickForm] Attribution d'une valeur par défaut à un select
    Par mohican13 dans le forum Bibliothèques et frameworks
    Réponses: 3
    Dernier message: 24/02/2006, 09h08
  4. Réponses: 6
    Dernier message: 14/02/2006, 21h53

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