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

SQL Oracle Discussion :

Problème de jointure externe avec les notations ANSI et Oracle


Sujet :

SQL Oracle

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juillet 2005
    Messages : 59
    Points : 46
    Points
    46
    Par défaut Problème de jointure externe avec les notations ANSI et Oracle
    Bonjour,

    J'ai actuellement un problème "relativement" gênant avec une requete au sein de laquelle je devrais utiliser une jointure externe.

    Ca ne marche simplement pas en notation ANSI (avec "RIGHT/LEFT OUTER JOIN")... Et ca ne marche que partiellement en notation oracle (avec "(+)"). Je m'explique, en utilisant la notation ANSI, le résultat est semblable à si j'utilisais une jointure interne (càd que le "résultat nul" ne s'affiche pas), alors qu'en utilisant la notation Oracle, j'ai bel et bien le résultat escompté.

    Mais malheureusement, de par ses limitations (impossibilité d'utiliser les IN ou les OR sur les colonnes de la table ou encore des > et < sur les colonnes de la jointure), la notation Oracle ne me convient pas non plus, car du coup, les conditions sont bien trop restrictives.

    Dans les requetes suivants, j'ai échangé les tables originelles par des "FROM dual" pour rendre l'exemple portable et non lié a des données qui bougent. Mes ensemble de données sont comme suit :
    ###############
    # _______d_______ #
    ###############
    # 2004 # 2 # 70'000 #
    # 2004 # 9 # 62'000 #
    # 2005 # 0 # 32'268 #
    # 2005 # 2 # 66'600 #
    # 2005 # 9 # 12'134 #
    ###############

    ####
    # t #
    ####
    # 0 #
    # 2 #
    # 9 #
    ####

    Et en faisant une jointure externe entre t et d, j'aimerais obtenir ceci :
    ###############
    # ____resultat_____ #
    ###############
    # ____ # 0 # _____ #
    # 2004 # 2 # 70'000 #
    # 2004 # 9 # 62'000 #
    ###############

    Voici donc comment j'ai écrit ma requete en format ANSI :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT d.dra_adec, dra_tcom, dra_avss
    FROM   (SELECT '2004' AS dra_adec, '2' AS dra_tcom, 3000    AS dra_avss FROM dual UNION
            SELECT '2004' AS dra_adec, '9' AS dra_tcom, 458.5   AS dra_avss FROM dual UNION
            SELECT '2005' AS dra_adec, '0' AS dra_tcom, 978.25  AS dra_avss FROM dual UNION
            SELECT '2005' AS dra_adec, '2' AS dra_tcom, 12541.1 AS dra_avss FROM dual UNION
            SELECT '2005' AS dra_adec, '9' AS dra_tcom, 40.5    AS dra_avss FROM dual) d
           RIGHT OUTER JOIN 
           (SELECT '0' AS dra_tcom FROM dual UNION 
            SELECT '2' AS dra_tcom FROM dual UNION
            SELECT '9' AS dra_tcom FROM dual) t USING (dra_tcom)
    WHERE  d.dra_adec = 2004
    ORDER BY d.dra_adec, dra_tcom;
    Mon résultat est malheureusement le suivant :

    ###############
    # ____resultat_____ #
    ###############
    # 2004 # 2 # 70'000 #
    # 2004 # 9 # 62'000 #
    ###############

    L'enregistrement avec la clé à 0 et le reste à NULL n'est donc pas présent. J'ai donc reformaté la requete pour utiliser la notation Oracle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT d.dra_adec, t.dra_tcom, dra_avss
    FROM   (SELECT '2004' AS dra_adec, '2' AS dra_tcom, 3000    AS dra_avss FROM dual UNION
            SELECT '2004' AS dra_adec, '9' AS dra_tcom, 458.5   AS dra_avss FROM dual UNION
            SELECT '2005' AS dra_adec, '0' AS dra_tcom, 978.25  AS dra_avss FROM dual UNION
            SELECT '2005' AS dra_adec, '2' AS dra_tcom, 12541.1 AS dra_avss FROM dual UNION
            SELECT '2005' AS dra_adec, '9' AS dra_tcom, 40.5    AS dra_avss FROM dual) d, 
           (SELECT '0' AS dra_tcom FROM dual UNION 
            SELECT '2' AS dra_tcom FROM dual UNION
            SELECT '9' AS dra_tcom FROM dual) t
    WHERE  d.dra_adec(+) = 2004
    AND    d.dra_tcom(+) = t.dra_tcom
    ORDER BY d.dra_adec, t.dra_tcom;
    Le résultat est cette fois ci conforme à ce que j'attendais :

    ###############
    # ____resultat_____ #
    ###############
    # ____ # 0 # _____ #
    # 2004 # 2 # 70'000 #
    # 2004 # 9 # 62'000 #
    ###############

    Mais maintenant, j'aimerais completer un peu la requete afin que plutot que de rechercher les données de l'année 2004, je recherche les données à partir de 2004. Je remplace donc le "=" par ">=" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT d.dra_adec, t.dra_tcom, dra_avss
    FROM   (SELECT '2004' AS dra_adec, '2' AS dra_tcom, 3000    AS dra_avss FROM dual UNION
            SELECT '2004' AS dra_adec, '9' AS dra_tcom, 458.5   AS dra_avss FROM dual UNION
            SELECT '2005' AS dra_adec, '0' AS dra_tcom, 978.25  AS dra_avss FROM dual UNION
            SELECT '2005' AS dra_adec, '2' AS dra_tcom, 12541.1 AS dra_avss FROM dual UNION
            SELECT '2005' AS dra_adec, '9' AS dra_tcom, 40.5    AS dra_avss FROM dual) d, 
           (SELECT '0' AS dra_tcom FROM dual UNION 
            SELECT '2' AS dra_tcom FROM dual UNION
            SELECT '9' AS dra_tcom FROM dual) t
    WHERE  d.dra_adec(+) >= 2004
    AND    d.dra_tcom(+) = t.dra_tcom
    ORDER BY d.dra_adec, t.dra_tcom;
    Mais la de nouveau, je n'obtiens pas ce que je veux, mais simplement :
    ###############
    # _______d_______ #
    ###############
    # 2004 # 2 # 70'000 #
    # 2004 # 9 # 62'000 #
    # 2005 # 0 # 32'268 #
    # 2005 # 2 # 66'600 #
    # 2005 # 9 # 12'134 #
    ###############

    Il manque donc l'enregistrement
    # ____ # 0 # _____ #

    Je suis un peu perdu du coup, avec la notation Oracle je n'arrive pas à faire tout ce que je veux et avec la notation ANSI je n'obtiens pas les bons résultats. Ou est-ce que je me suis trompé?



    Merci pour la lecture de ce pavé

    Lucas

  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 383
    Points
    18 383
    Par défaut
    Votre requête est mal écrite, quand vous voulez passez des conditions sur une jointure externe soit vous écrivez une sous-requête, soit vous écrivez la condition dans la jointure (ce qui est un grand confort) :
    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
    SELECT d.dra_adec, t.dra_tcom, d.dra_avss
    FROM
        (
        SELECT '2004' AS dra_adec, '2' AS dra_tcom, 3000 AS dra_avss FROM dual UNION ALL
        SELECT '2004', '9', 458.5   FROM dual UNION ALL
        SELECT '2005', '0', 978.25  FROM dual UNION ALL
        SELECT '2005', '2', 12541.1 FROM dual UNION ALL
        SELECT '2005', '9', 40.5    FROM dual
        ) d
        RIGHT OUTER JOIN 
        (
        SELECT '0' AS dra_tcom FROM dual UNION ALL
        SELECT '2' FROM dual UNION ALL
        SELECT '9' FROM dual
        ) t 
          ON t.dra_tcom = d.dra_tcom
         AND d.dra_adec = '2004'
    ORDER BY d.dra_adec asc, t.dra_tcom asc;

  3. #3
    Expert éminent
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Developer Advocate YugabyteDB
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 821
    Points : 6 443
    Points
    6 443
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Comme le précise Waldar en notation ANSI une condition dans la clause where n'est pas la même qu'une condition dans la clause ON

    Maintenant pour le cas >=

    Je ne comprends pas pourquoi tu veux:
    # ____ # 0 # _____ #
    car quelle est la signification de cet enregistrement ?

    Celà voudrait dire 'il n'y a pas de valeur pour la clé 0' alors que ce n'est pas vrai.

    Je suppose que tu veux plutôt dire 'il n'y a pas de valeur pour la clé 0 en 2004, donc:
    # 2004 # 0 # _____ #

    et là, en 10g c'est facile avec les 'partition outer join'
    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
    SELECT d.dra_adec, t.dra_tcom, d.dra_avss
    FROM
        (
        SELECT '2004' AS dra_adec, '2' AS dra_tcom, 3000 AS dra_avss FROM dual UNION ALL
        SELECT '2004', '9', 458.5   FROM dual UNION ALL
        SELECT '2005', '0', 978.25  FROM dual UNION ALL
        SELECT '2005', '2', 12541.1 FROM dual UNION ALL
        SELECT '2005', '9', 40.5    FROM dual
        ) d partition by ( d.dra_adec )
        RIGHT OUTER JOIN
        (
        SELECT '0' AS dra_tcom FROM dual UNION ALL
        SELECT '2' FROM dual UNION ALL
        SELECT '9' FROM dual
        ) t
          ON ( t.dra_tcom = d.dra_tcom AND d.dra_adec >= '2004')
    ORDER BY d.dra_adec ASC, t.dra_tcom ASC
    /
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    DRA_ADEC DRA_TCOM   DRA_AVSS
    -------- -------- ----------
    2004     0
    2004     2              3000
    2004     9             458.5
    2005     0            978.25
    2005     2           12541.1
    2005     9              40.5
    Cordialement,
    Franck.
    Franck Pachot - Developer Advocate Yugabyte 🚀 Base de Données distribuée, open source, compatible PostgreSQL
    🗣 twitter: @FranckPachot - 📝 blog: blog.pachot.net - 🎧 podcast en français : https://anchor.fm/franckpachot

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juillet 2005
    Messages : 59
    Points : 46
    Points
    46
    Par défaut
    Merci beaucoup, je ne pensais pas que ca avait une influence de mettre les paramêtres à un endroit ou l'autre... Je vais tester ca dès demain

    Je suppose que tu veux plutôt dire 'il n'y a pas de valeur pour la clé 0 en 2004, donc:
    # 2004 # 0 # _____ #
    Effectivement, après réflexion, c'est bien le couple année (2004) et index (0) que je veux et par chance, d'ici à ce que cette requete soit en prod, on devrait être passé à la 10g


    Merci pour votre aide à tous les deux!

    Lucas

  5. #5
    Expert éminent
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Developer Advocate YugabyteDB
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 821
    Points : 6 443
    Points
    6 443
    Billets dans le blog
    1
    Par défaut
    Bonjour,
    Sur le fait que la signification d'un prédicat est différente dans la clause de jointure et dans la clause where, l'explication est simple: la clause where vérifie les prédicats après la jointure. Et après la jointure externe, la valeur des champs de la table ou il n'y a pas de correspondance sont tous NULL.
    Donc dans ce cas, le prédicat NULL >= 2004 ne sera jamais vrai. jointure
    Cordialement
    Franck.
    Franck Pachot - Developer Advocate Yugabyte 🚀 Base de Données distribuée, open source, compatible PostgreSQL
    🗣 twitter: @FranckPachot - 📝 blog: blog.pachot.net - 🎧 podcast en français : https://anchor.fm/franckpachot

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juillet 2005
    Messages : 59
    Points : 46
    Points
    46
    Par défaut
    Ca marche bien, c'est parfait, merci. C'est vrai qu'a la base, j'ai même pas eu l'idée d'essayer de mettre mes conditions au sein de la jointure... Mais avec l'explication, c'est sur que ca parait logique

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 29/10/2007, 13h04
  2. [Avis aux pros !] Problèmes de la VCL avec les threads
    Par benj63 dans le forum C++Builder
    Réponses: 3
    Dernier message: 17/02/2006, 22h38
  3. Problème sur classe Transformer avec les <!--
    Par tykool dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 10/01/2006, 10h20
  4. [SQL] jointure externe avec 3 tables, comment faire ....
    Par grumbok dans le forum Langage SQL
    Réponses: 2
    Dernier message: 04/08/2005, 16h13
  5. jointure externe avec un where, me pose problème!
    Par Danae dans le forum Langage SQL
    Réponses: 3
    Dernier message: 18/07/2005, 17h37

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