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

 Oracle Discussion :

Jointure : question de syntaxe ou performance


Sujet :

Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    759
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 759
    Par défaut Jointure : question de syntaxe ou performance
    Bonjour,

    Table MA_TABLE (A, Bfk, C, D)
    où Bfk est une colonne que l'on peut jondre la table Tb (FK)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select t.* from MA_TABLE t
    join Tb on Tb.Bfk = t.Bfk
    where Tb.filtre1 = 2 and Tb.filtre2 = 'V'
    est-il différent de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    select t.* from MA_TABLE t
    join Tb on (Tb.Bfk = t.Bfk and Tb.filtre1 = 2 and Tb.filtre2 = 'V')

    En fait j'essaie aussi d'optimiser cette requête (longue!)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    select *
    from t1
    join t2_v1 on t2_v1.a = t1.a
    join t2_v2 on t2_v2.a = t1.a
    left join t3_v1 on (t3_v1.b = t2_v1.b and t3_v1.filtre1 = 1 and Tb.filtre2 = 'V')
    left join t3_v2 on (t3_v2.b = t2_v2.b and t3_v2.filtre1 = 2 and Tb.filtre2 = 'V')
    ...
    where...
    mais on ne peut pas faire 2 outer join sur la même table donc ça, ça ne marche pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select *
    from t1
    join t2 on t2.a = t1.a
    left join t3_v1 on (t3_v1.b = t2.b and t3_v1.filtre1 = 1 and Tb.filtre2 = 'V')
    left join t3_v2 on (t3_v2.b = t2.b and t3_v2.filtre1 = 2 and Tb.filtre2 = 'V')
    ...
    where...

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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 454
    Par défaut
    Citation Envoyé par stof Voir le message
    Table MA_TABLE (A, Bfk, C, D)
    où Bfk est une jointure vers les la table Tb
    Attention au vocabulaire, c'est important. Une colonne n'est pas une jointure.
    Une jointure n'existe que lors d'une requête, tandis qu'une colonne est persistante.
    Peut-être vouliez-vous parler d'une clef étrangère, ou encore d'une colonne commune ?

    Citation Envoyé par stof Voir le message
    REQUETE1 est-il différent de REQUETE2
    Dans le cas exposé ici, les deux requêtes sont identiques.
    Mais c'est parce que vous l'avez présenté avec une jointure forte (JOIN simple, équivalent à INNER JOIN).
    Avec une jointure externe les requêtes sont différentes.

    Citation Envoyé par stof Voir le message
    En fait j'essaie aussi d'optimiser cette requête (longue!)
    Est-ce que vos tables ou vues t2_v1 / t2_v2 et t3_v1 / t3_v2 sont les mêmes ?
    Dans la clause de jointure avec t3_v2 vous n'y faites pas référence, je pense que c'est une erreur lors de l'écriture de la requête ici.

    Si ce n'est pas confidentiel, n'hésitez pas a publier l'intégralité de votre requête. Si ça l'est, il suffit de changer le nom des objets.

    Citation Envoyé par stof Voir le message
    mais on ne peut pas faire 2 outer join sur la même table donc ça ça ne marche pas
    Je pense que vous vous exprimez mal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    select t1.dummy as dummy_t1
         , t2.dummy as dummy_t2
         , t3.dummy as dummy_t3
      from dual t1
           left outer join dual t2
             on t2.dummy = t1.dummy
           left outer join dual t3
             on t3.dummy = t1.dummy;
     
    DUMMY_T1 DUMMY_T2 DUMMY_T3
    -------- -------- --------
    X        X        X

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    759
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 759
    Par défaut
    J'ai corrigé ma question (oui, t2_v1 / t2_v2 et t3_v1 / t3_v2 désignent une même table t2 et t3).

    Puisque tu veux la requête complète, la voilà mais c'est imbuvable quand on ne connait pas le modèle à mon avis :
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    select rownum, t.* 
    from ( 
    select distinct 
    sRef.TITIDT as TITRefIDT, 
    sCpt.TITIDT as TITCptIDT, 
    nvl(( 
    	     select RefREFEXT  
    	     from RefREF aRef 
    	     where aRef.TITIDT = tRef.TITIDT 
    	     and aRef.RefTITIDT = tRef.RefTITIDT 
    	     and aRef.PERTPSDATDEB =(select max(t1.PERTPSDATDEB) from RefREF t1 where t1.PVDIDT != 2 and t1.RefTITIDT = aRef.RefTITIDT and t1.PERTPSDATDEB <= R.DATVL) 
       ), nvl(tRef.RefCOD2,ptRef.PVDTITCOD)) as CODRef, 
    ptCpt.PVDTITCOD as CODCpt, 
    ptRef.PVDTITLIB as LIBRef, 
    ptCpt.PVDTITLIB as LIBCpt, 
    r.DATVL, 
    crsRef.CRSVLO as CRSRef, 
    crsCpt.CRSVLO as CRSCpt, 
    sRef.PLACOTCOD as PLACOTRef, 
    sCpt.PLACOTCOD as PLACOTCpt 
    from RPM r 
    join LIGRPM lr on lr.RPMIDT = r.RPMIDT 
    left join LIGRPMINVLIG lrlRef on lrlRef.LIGRPMIDT = lr.LIGRPMIDT 
    left join LIGRPMINVLIG lrlCpt on lrlCpt.LIGRPMIDT = lr.LIGRPMIDT 
    left join INVLIG ilRef on (ilRef.INVLIGIDT = lrlRef.INVLIGIDT and ilRef.PVDIDT = 2 and ilRef.FLGLIQ = 'F') 
    left join INVLIG ilCpt on (ilCpt.INVLIGIDT = lrlCpt.INVLIGIDT and ilCpt.PVDIDT = r.PVD_PVDIDT and ilCpt.FLGLIQ = 'F') 
    left join STK sRef on sRef.INVLIGIDT = ilRef.INVLIGIDT 
    left join STK sCpt on sCpt.INVLIGIDT = ilCpt.INVLIGIDT 
    left join PVDTIT ptRef on (ptRef.TITIDT = sRef.TITIDT and ptRef.PVDIDT = ilRef.PVDIDT) 
    left join PVDTIT ptCpt on (ptCpt.TITIDT = sCpt.TITIDT and ptCpt.PVDIDT = ilCpt.PVDIDT) 
    left join RefTIT tRef on (tRef.TITIDT = sRef.TITIDT and tRef.STALIGIDT in (select STALIGIDT from STALIG where PVDIDT = r.PVD_PVDIDT and STALIGCOD = case when sRef.QTETIT > 0 then 'RECU' else 'VERSE' end))
    left join CRS crsRef on crsRef.CRSIDT = sRef.CRSIDT 
    left join CRS crsCpt on crsCpt.CRSIDT = sCpt.CRSIDT 
    where r.DATVL = to_date('26/12/2011', 'DD/MM/YYYY')
    and (ptRef.PVDTITCOD is null or ptRef.PVDTITCOD = (select max(PVDTITCOD) from PVDTIT t1 where t1.PVDIDT = 2 and t1.TITIDT = ptRef.TITIDT)) 
    and (ptCpt.PVDTITCOD is null or ptCpt.PVDTITCOD = (select max(PVDTITCOD) from PVDTIT t2 where t2.PVDIDT != 2 and t2.TITIDT = ptCpt.TITIDT)) 
    and (crsRef.CRSVLO is not null or crsCpt.CRSVLO is not null) 
    order by ptRef.PVDTITLIB asc 
    ) t

  4. #4
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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 454
    Par défaut
    Est-ce que la requête ci-dessous est équivalente en terme de résultat ?
    J'ai remplacé certaines sous-requêtes par des jointures.
    Quels sont exactement vos problèmes de performance (volumétries, temps de réponses, explain plan) ?
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    With PVDTIT_AGG AS
    (
      SELECT TITIDT
           , MAX(CASE WHEN PVDIDT  = 2 THEN PVDTITCOD END) AS PVDTITCOD_EQ_2
           , MAX(CASE WHEN PVDIDT <> 2 THEN PVDTITCOD END) AS PVDTITCOD_DF_2
        FROM PVDTIT
    GROUP BY TITIDT
    )
      SELECT DISTINCT 
             sRef.TITIDT AS TITRefIDT
           , sCpt.TITIDT AS TITCptIDT
           , coalesce(aRef.RefREFEXT, tRef.RefCOD2, ptRef.PVDTITCOD) AS CODRef
           , ptCpt.PVDTITCOD AS CODCpt
           , ptRef.PVDTITLIB AS LIBRef
           , ptCpt.PVDTITLIB AS LIBCpt
           , r.DATVL
           , crsRef.CRSVLO   AS CRSRef
           , crsCpt.CRSVLO   AS CRSCpt
           , sRef.PLACOTCOD  AS PLACOTRef
           , sCpt.PLACOTCOD  AS PLACOTCpt 
        FROM RPM r
             INNER JOIN LIGRPM lr
               ON lr.RPMIDT = r.RPMIDT
             LEFT OUTER JOIN LIGRPMINVLIG lrl
               ON lrl.LIGRPMIDT = lr.LIGRPMIDT
             LEFT OUTER JOIN INVLIG ilRef
               ON ilRef.INVLIGIDT = lrl.INVLIGIDT
              AND ilRef.PVDIDT = 2
              AND ilRef.FLGLIQ = 'F'
             LEFT OUTER JOIN STK sRef
               ON sRef.INVLIGIDT = ilRef.INVLIGIDT
             LEFT OUTER JOIN PVDTIT_AGG ptaRef
               ON ptaRef.TITIDT = = sRef.TITIDT
             LEFT OUTER JOIN PVDTIT ptRef
               ON ptRef.TITIDT = ptaRef.TITIDT
              AND ptRef.PVDIDT = 2
              AND ptRef.PVDTITCOD = ptaRef.PVDTITCOD_EQ_2
             LEFT OUTER JOIN RefTIT tRef
               ON tRef.TITIDT = sRef.TITIDT
              AND tRef.STALIGIDT IN (SELECT st.STALIGIDT
                                       FROM STALIG st
                                      WHERE st.PVDIDT = r.PVD_PVDIDT
                                        AND st.STALIGCOD = case when sRef.QTETIT > 0 then 'RECU' else 'VERSE' end)
             LEFT OUTER JOIN RefREF aRef
               ON aRef.TITIDT    = tRef.TITIDT 
              AND aRef.RefTITIDT = tRef.RefTITIDT
              AND aRef.PERTPSDATDEB = (SELECT max(t1.PERTPSDATDEB)
                                         FROM RefREF t1
                                        WHERE t1.PVDIDT <> 2
                                          AND t1.RefTITIDT = aRef.RefTITIDT
                                          AND t1.PERTPSDATDEB <= R.DATVL)
             LEFT OUTER JOIN CRS crsRef
               ON crsRef.CRSIDT = sRef.CRSIDT
             LEFT OUTER JOIN INVLIG ilCpt
               ON ilCpt.INVLIGIDT = lrl.INVLIGIDT
              AND ilCpt.PVDIDT = r.PVD_PVDIDT
              AND ilCpt.FLGLIQ = 'F'
             LEFT OUTER JOIN STK sCpt
               ON sCpt.INVLIGIDT = ilCpt.INVLIGIDT
             LEFT OUTER JOIN PVDTIT_AGG ptasCpt
               ON ptasCpt.TITIDT = = sCpt.TITIDT
             LEFT OUTER JOIN PVDTIT ptCpt
               ON ptCpt.TITIDT = ptasCpt.TITIDT
              AND ptCpt.PVDIDT = ilCpt.PVDIDT
              AND ptCpt.PVDTITCOD = ptasCpt.PVDTITCOD_DF_2
             LEFT OUTER JOIN CRS crsCpt
               ON crsCpt.CRSIDT = sCpt.CRSIDT
       WHERE r.DATVL = to_date('26/12/2011', 'DD/MM/YYYY')
         AND (crsRef.CRSVLO IS NOT NULL
          OR  crsCpt.CRSVLO IS NOT NULL) 
    ORDER BY ptRef.PVDTITLIB ASC;

  5. #5
    Membre Expert

    Homme Profil pro
    Inscrit en
    Mars 2010
    Messages
    536
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 536
    Par défaut
    Fabien,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    FROM RPM r
             INNER JOIN LIGRPM lr
               ON lr.RPMIDT = r.RPMIDT
             LEFT OUTER JOIN LIGRPMINVLIG lrl
               ON lrl.LIGRPMIDT = lr.LIGRPMIDT
             LEFT OUTER JOIN INVLIG ilRef
               ON ilRef.INVLIGIDT = lrl.INVLIGIDT
              AND ilRef.PVDIDT = 2
              AND ilRef.FLGLIQ = 'F'
    Pouvez-vous m'expliquer l'intérêt de la jointure externe sur INVLIG ilRef lorsque vous la suivez de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
              AND ilRef.PVDIDT = 2
              AND ilRef.FLGLIQ = 'F'

  6. #6
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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 454
    Par défaut
    Citation Envoyé par Mohamed.Houri Voir le message
    Pouvez-vous m'expliquer l'intérêt de la jointure externe sur INVLIG ilRef lorsque vous la suivez de...
    Bien sûr, les filtres s'ils sont présents au niveau de la jointure conservent le côté externe de celle-ci.
    C'est strictement équivalent à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
             LEFT OUTER JOIN LIGRPMINVLIG lrl
               ON lrl.LIGRPMIDT = lr.LIGRPMIDT
             LEFT OUTER JOIN (select *
                                from INVLIG 
                               where PVDIDT = 2
                                 AND FLGLIQ = 'F') ilRef
               ON ilRef.INVLIGIDT = lrl.INVLIGIDT
    Stof, j'ai repris votre requête à l'identique, je pensais qu'elle fonctionnait puisque vous parliez d'optimisation.

    Idéalement un petit jeu de données sur les tables impliquées par cette jointure permettra de bien analyser le besoin.

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    759
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 759
    Par défaut
    Merci pour ta réponse. j'apprendrai au moins dans un premier temps l'existence de "WITH xxx AS".

    Sinon en dehors de la faute de frappe du ==, la requête ne fonctionne pas car tu tombes comme moi un moment sur la limitation qui donne envie de s'arracher les cheveux dans la section :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
             LEFT OUTER JOIN RefREF aRef
               ON aRef.TITIDT    = tRef.TITIDT 
              AND aRef.RefTITIDT = tRef.RefTITIDT
              AND aRef.PERTPSDATDEB = (SELECT max(t1.PERTPSDATDEB)
                                         FROM RefREF t1
                                        WHERE t1.PVDIDT <> 2
                                          AND t1.RefTITIDT = aRef.RefTITIDT
                                          AND t1.PERTPSDATDEB <= R.DATVL)
    ORA-01799: a column may not be outer-joined to a subquery

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

Discussions similaires

  1. Question de syntaxe
    Par dafalri dans le forum VB 6 et antérieur
    Réponses: 12
    Dernier message: 13/12/2005, 20h57
  2. [XML] Questions de syntaxe
    Par ghohm dans le forum XML/XSL et SOAP
    Réponses: 4
    Dernier message: 03/11/2005, 12h08
  3. question sur syntaxe d'une requete
    Par sparis dans le forum MS SQL Server
    Réponses: 8
    Dernier message: 29/09/2005, 11h58
  4. [C linux makefile] question de syntaxe
    Par Ultros dans le forum Systèmes de compilation
    Réponses: 7
    Dernier message: 09/04/2004, 07h58
  5. Réponses: 2
    Dernier message: 08/03/2004, 15h10

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