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 504
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : août 2008
    Messages : 2 504
    Points : 4 832
    Points
    4 832

    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
    Ingénieur d'études décisionnel
    Inscrit en
    mai 2002
    Messages
    7 199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur d'études décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : mai 2002
    Messages : 7 199
    Points : 21 986
    Points
    21 986

    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
            )
    ;
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  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
    Inscrit en
    janvier 2010
    Messages
    4 380
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : janvier 2010
    Messages : 4 380
    Points : 8 861
    Points
    8 861

    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
    Ingénieur d'études décisionnel
    Inscrit en
    mai 2002
    Messages
    7 199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur d'études décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : mai 2002
    Messages : 7 199
    Points : 21 986
    Points
    21 986

    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.
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  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, 12h06
  2. Réponses: 5
    Dernier message: 01/02/2013, 13h19
  3. [QuickForm] Attribution d'une valeur par défaut à un select
    Par mohican13 dans le forum HTML_quickform
    Réponses: 3
    Dernier message: 24/02/2006, 08h08
  4. Réponses: 6
    Dernier message: 14/02/2006, 20h53

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