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 :

Faire une jointure gauche composée d'un sous ensemble filtré sur un élément de la table principale [11gR2]


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juin 2005
    Messages
    58
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 58
    Par défaut Faire une jointure gauche composée d'un sous ensemble filtré sur un élément de la table principale
    Bonjour à tous,

    Je viens vers vous aujourd'hui car j'essaie de résoudre le problème suivant :

    Comme faire une jointure gauche composée d'un sous ensemble filtré sur un élément de la table principale.
    L'énoncé ne doit pas être très clair, alors voici une requête d'illustration :

    La requête qui fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT 
    T1.ID,
    ALIAS_T2.FIELD1 
    FROM T1
    LEFT JOIN (SELECT FIELD1 , FIELD2, FIELD3, row_number() over (partition by FIELD1,FIELD2 order by FIELD1) as RAWNUM FROM T2) ALIAS_T2 ON
    ALIAS_T2.FIELD1 = T1.T2FIELD1 AND ALIAS_T2.FIELD2 = T1.T2FIELD2
    AND ALIAS_T2.RAWNUM = 1
    Donc ça, ça fonctionne, ce que j'aimerais faire c'est appliquer le filtrage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ALIAS_T2.FIELD1 = T1.T2FIELD1 AND ALIAS_T2.FIELD2 = T1.T2FIELD2
    dans la sous-requête afin que cet ensemble soit beaucoup plus léger en mémoire.
    Ca donnerais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT 
    T1.ID,
    ALIAS_T2.FIELD1
    FROM T1
    LEFT JOIN (SELECT FIELD1 , FIELD2, FIELD3, row_number() over (partition by FIELD1,FIELD2 order by FIELD1) as RAWNUM FROM T2 where ALIAS_T2.FIELD1 = T1.T2FIELD1 AND ALIAS_T2.FIELD2 = T1.T2FIELD2) ALIAS_T2 ON
    ALIAS_T2.RAWNUM = 1

    Le seul truc c'est que dans la sous-requête il ne connait pas T1 et ses champs, j'ai donc droit à l'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ORA-00904: "T1"."FIELD1" : identificateur non valide
    00904. 00000 -  "%s: invalid identifier"
    Donc mes questions
    Est-ce moi qui utilise une mauvaise syntaxe ?
    Est-il impossible de faire référence à T1 dans la sous requête ?
    Existe-il un contournement à ce type de problématiques ?
    Oracle est-il intelligent ? Dans le sens : rajoute-il lui-même les conditions qui sont sont derrière le "ON" de la jointe dans le "where" de la sous-requête ? (et dans ce cas je me pose des questions existentielles pour rien)

    Merci d'avance pour vos retour.

  2. #2
    Membre expérimenté
    Homme Profil pro
    Ingénieur en études décisionnelles
    Inscrit en
    Février 2013
    Messages
    134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur en études décisionnelles

    Informations forums :
    Inscription : Février 2013
    Messages : 134
    Par défaut
    Bonjour,

    Si je comprends bien, tu veux appliquer ta condition de jointure dans ta sous-requête pour ne ramener que les lignes présentes dans T1. C'est ça ?
    Si c'est bien ça, tu peux remplacer ton left join par un inner join, ça fera la même chose.

    Ensuite, Oracle est "intelligent", dans le sens où il a des moyens pour connaître la meilleure façon d'accéder aux données. Tu peux faire des recherches sur les "explain plan" pour découvrir comment les requêtes sont interprétées.
    Si ta requête initiale ne s'exécute pas, c'est peut-être tout simplement que tu as un problème de statistiques.

  3. #3
    Membre averti
    Inscrit en
    Juin 2005
    Messages
    58
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 58
    Par défaut
    Bonjour,

    Merci d'avoir regardé.

    Alors non en fait je ne peux pas faire un inner, sinon je ne peux plus tester avec IS NULL que ma jointure n'est pas satisfaite.

    Le principe fonctionnel de la requête est le suivant :

    Permettre de tester la validité de la catégorisation d'une ligne de T1 , la catégorisation est à 5 niveaux, avec chaque niveau dépendant du précédent et je répète la jointure 5 fois ce qui me permet avec un switch case dans le select , afin d'afficher à quel niveau il y a une donnée de catégorisation manquante.
    Dans ma requête d'exemple je n'ai mis qu'une seule jointure et n'ai pas mis le switch.

    Si je ne passe pas par des sous-requêtes, on se retrouve avec des produits cartésiens à chaque niveau et on se retrouve avec une requête qui met à genoux le serveur.

    Je cherche juste à savoir si je peux optimiser chaque jointure, car elle revient à charger la table en mémoire et à filtrer ensuite.

  4. #4
    Membre averti
    Inscrit en
    Juin 2005
    Messages
    58
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 58
    Par défaut
    Rebonjour,

    J'ai trouvé un contournement :

    Mettre la sous-requête directement dans le switch case ce qui permet de pouvoir mettre une condition avec un champ de T1 dans la clause WHERE de la sous-requête.
    Une sous requête dans un select oracle, veut bien ramener la valeur de table principale, une sous requête dans un join il ne veut plus

    Ça donne un truc comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    SELECT * FROM (
    SELECT 
    T1.ID,
    ALIAS_T2.FIELD1,
    CASE
    WHEN T1.T2FIELD2 IS NOT NULL AND (SELECT COUNT(1) FROM T2 WHERE T2.FIELD1 = T1.T2FIELD1 AND ROWNUM = 1) <> 1 
    THEN 'FIELD1 KO'
    END AS "ErrorType"
    FROM T1) TempTable
    WHERE ErrorType IS NOT NULL
    On rajoute un WHEN pour chaque cas de figure et ça roule.

    Et c'est beaucoup beaucoup plus rapide ! (surtout avec mes 5 niveaux de vérif)

  5. #5
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Bref il existe une équivalence entre une requête scalaire et une jointure externe.
    Parfois la requête scalaire se comporte mieux parfois non!

    Je n'aime pas cette sous-requête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT COUNT(1) FROM T2 WHERE T2.FIELD1 = T1.T2FIELD1 AND ROWNUM = 1
    Il y des autre façons plus compréhensibles pour l'écrire.

  6. #6
    Membre averti
    Inscrit en
    Juin 2005
    Messages
    58
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 58
    Par défaut
    Tu proposerais quoi ?

    Éventuellement ce que je verrais c'est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT 1 FROM T2 WHERE T2.FIELD1 = T1.T2FIELD1 AND ROWNUM = 1
    Pour éviter le count, bien qu'il ne doive pas couter bien cher celui là.

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

Discussions similaires

  1. [Hibernate 3] [Criteria] Faire une jointure avec Criteria
    Par bouchette63 dans le forum Hibernate
    Réponses: 30
    Dernier message: 07/06/2010, 17h54
  2. Réponses: 1
    Dernier message: 09/11/2006, 12h08
  3. faire une jointure sur des clés différentes
    Par phpaide dans le forum Requêtes
    Réponses: 3
    Dernier message: 13/09/2006, 10h16
  4. Comment faire une jointure ?
    Par Terminator dans le forum Langage SQL
    Réponses: 12
    Dernier message: 16/10/2005, 13h26
  5. [CR9] faire une Jointure externe
    Par coldec dans le forum SAP Crystal Reports
    Réponses: 5
    Dernier message: 28/06/2005, 12h10

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