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 :

OUTER JOIN avec un OR


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Mars 2007
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 59
    Par défaut OUTER JOIN avec un OR
    Bonjour,

    Je voudrais effectuer une query du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT NVL(A.LABEL,'~')
    FROM TABLE_A A, TABLE_B B
    WHERE A.KEY (+) = B.KEY||'0001' OR
              A.KEY (+)= B.KEY||'0002'
    Je voudrais que ça me retourne tous les records de la TABLE_B avec la clé de la TABLE_A si il y a un match avec les deux conditions.

    S'il y a un match avec les deux conditions le label sera d'office le meme...donc pas de problème à ce niveau la...

    Mais le problème est qu'on ne peut pas utiliser un outer join avec un OR ou IN.

    Y a-t-il une alternative?

    Merci.

  2. #2
    Rédacteur

    Homme Profil pro
    Développeur et DBA Oracle
    Inscrit en
    Octobre 2006
    Messages
    878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur et DBA Oracle

    Informations forums :
    Inscription : Octobre 2006
    Messages : 878
    Par défaut
    Salut,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT NVL(A.LABEL,'~')
    FROM TABLE_A A, TABLE_B B
    WHERE A.KEY (+) = B.KEY||'0001' 
    union
    SELECT NVL(A.LABEL,'~')
    FROM TABLE_A A, TABLE_B B
    WHERE A.KEY (+)= B.KEY||'0002'
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT NVL(A.LABEL,'~')
    FROM TABLE_A A, ( select key||'0001'  key,..... from TABLE_B
                               union
                                select key||'0002' ,......... from TABLE_B)  B
    WHERE A.KEY (+) = B.KEY

  3. #3
    Membre confirmé
    Inscrit en
    Mars 2007
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 59
    Par défaut
    Citation Envoyé par salim11
    Salut,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT NVL(A.LABEL,'~')
    FROM TABLE_A A, TABLE_B B
    WHERE A.KEY (+) = B.KEY||'0001' 
    union
    SELECT NVL(A.LABEL,'~')
    FROM TABLE_A A, TABLE_B B
    WHERE A.KEY (+)= B.KEY||'0002'
    En faite j'avais déjà testé ainsi, les deux outer join sont très rapides mais le union me pose des problèmes au niveau de la performance.

  4. #4
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Par défaut
    Citation Envoyé par Ujitsu
    Y a-t-il une alternative?
    Quelle est ta version


    Dans oracle9, tu peux faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select * from t1 left join t2 on (a=b+1 or a=b+2)

  5. #5
    Expert confirmé
    Homme Profil pro
    Big Data / Freelance EURL
    Inscrit en
    Mars 2003
    Messages
    2 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Big Data / Freelance EURL

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 124
    Par défaut
    Ujitsu de toute façon avec tes concaténations dans des jointures ou des clauses WHERE ça fait sauter les index et donc la performance.

    Mais détaillons en SQL ansi 92
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT NVL(A.LABEL,'~') 
    FROM TABLE_A A
    RIGHT JOIN  TABLE_B B 
    ON (A.KEY = B.KEY||'0001' OR  A.KEY = B.KEY||'0002')
    souvent en mettant ALL on gagne de la performance quitte à regrouper dans une sur-requête.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    select distinct LABEL from 
    (SELECT NVL(A.LABEL,'~')  LABEL
    FROM TABLE_A A, TABLE_B B 
    WHERE A.KEY (+) = B.KEY||'0001' 
    union ALL
    SELECT NVL(A.LABEL,'~') 
    FROM TABLE_A A, TABLE_B B 
    WHERE A.KEY (+) =  B.KEY||'0002')

  6. #6
    McM
    McM est déconnecté
    Expert confirmé

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par phili_b
    souvent en mettant ALL on gagne de la performance quitte à regrouper dans une sur-requête.
    Ah bon ? un UNION fait un distinct sur les colonnes, un UNION ALL non.
    Je vois pas en quoi faire un UNION ALL puis un DISTINCT va être plus performant qu'un UNION.

    Je vais tester ça.

  7. #7
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Par défaut
    Citation Envoyé par phili_b
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    select distinct LABEL from 
    (SELECT NVL(A.LABEL,'~')  LABEL
    FROM TABLE_A A, TABLE_B B 
    WHERE A.KEY (+) = B.KEY||'0001' 
    union ALL
    SELECT NVL(A.LABEL,'~') 
    FROM TABLE_A A, TABLE_B B 
    WHERE A.KEY (+) =  B.KEY||'0002')
    ce n'est bien sûr pas pareil de faire

    select x from t1 union select y from t2
    et
    select distinct x from t1 union all select y from t2

    car les doublons ne sont supprimés que dans t1 dans la 2e requête

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    SQL> select * from dual union select * from dual;
     
    D
    -
    X
     
    SQL> select distinct * from dual union all select * from dual;
     
    D
    -
    X
    X
    Ujitsu ne nous a toujours pas donné sa version

  8. #8
    Expert confirmé
    Homme Profil pro
    Big Data / Freelance EURL
    Inscrit en
    Mars 2003
    Messages
    2 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Big Data / Freelance EURL

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 124
    Par défaut
    Citation Envoyé par laurentschneider
    ce n'est bien sûr pas pareil de faire
    select x from t1 union select y from t2
    et
    select distinct x from t1 union all select y from t2
    Certes mais tu as mal repris mon exemple: Mon union all se trouve à l'intérieur d'une sous-requête et le distinct à l'extérieur, tandis que dans ton exemple le distinct ne porte que sur la première requête.

    Moi il s'agissait de cela.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    select distinct dummy from ( 
      select  dummy from dual 
      union all 
      select dummy from dual);
    DUMMY
    -----
    X    
    1 row selected
    Et dans ce cas c'est pareil du point de vue du résultat.

    Par contre l'avantage de faire UNION ALL puis DISTINCT, plutôt que UNION seulement, c'est qu'il ne se pose pas de question de dédoublonnage au moment de chaque SELECT, ce n'est que dans un deuxième temps qu'il dédoublonne grâce au DISTINCT (ou au group by dans l'absolu).

    Petite recherche sur developpez.com. C'est du db2 mais comme la problèmatique est plus SQL que particulèrement Oracle:
    Optimisez vos requêtes DB2 : Union et Union All

    extrait:
    Si vous savez avec certitude que les commandes UNION et UNION ALL vont retourner le même résultat, utilisez UNION ALL. En effet, la commande UNION induit un tri pour éliminer les doublons. L'utilisation de UNION ALL va donc vous faire économiser ce temps.
    suite de l'explication dans l'url.

    En tout cas dans mes cas pratiques à fort volume c'est flagrand que distinct + union all est bien plus performant que union tout court.

  9. #9
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Par défaut
    Citation Envoyé par phili_b
    Certes mais tu as mal repris mon exemple
    oops


    bon, j'ai fait un petit test et il me parait interessant de comparer les plans

    <...>

    Quand tu fais un UNION, Oracle de lui-même fait un UNION ALL dans son plan. Ce que fait DB2 je n'en sais rien.


    Plus intéressant, en 10gR2, il y a un nouveau type d'opération, le HASH UNIQUE (qui ne trie pas les lignes)
    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
     
    SQL>  select distinct x from (select x from t1 union all select x from t2);
     
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 3647663411
     
    ------------------------------------------------------------------------------
    | Id  | Operation             | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT      |      |     3 |     6 |   623  (37)| 00:00:08 |
    |   1 |  HASH UNIQUE          |      |     3 |     6 |   623  (37)| 00:00:08 |
    |   2 |   VIEW                |      |  1151K|  2248K|   430   (8)| 00:00:06 |
    |   3 |    UNION-ALL PARTITION|      |       |       |            |          |
    |   4 |     TABLE ACCESS FULL | T1   |   801K|  1565K|   300   (8)| 00:00:04 |
    |   5 |     TABLE ACCESS FULL | T2   |   349K|   683K|   132   (8)| 00:00:02 |
    ------------------------------------------------------------------------------
     
    SQL> select x from t1 union select x from t2;
     
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 1979990680
     
    ------------------------------------------------------------------------------------
    | Id  | Operation           | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |      |  1151K|  2248K|       |  3456  (36)| 00:00:42 |
    |   1 |  SORT UNIQUE        |      |  1151K|  2248K|    17M|  3456  (36)| 00:00:42 |
    |   2 |   UNION-ALL         |      |       |       |       |            |          |
    |   3 |    TABLE ACCESS FULL| T1   |   801K|  1565K|       |   300   (8)| 00:00:04 |
    |   4 |    TABLE ACCESS FULL| T2   |   349K|   683K|       |   132   (8)| 00:00:02 |
    ------------------------------------------------------------------------------------
    je ne comprends pas pourquoi, mais UNION trie les lignes. Sans doute un problème du CBO

  10. #10
    Membre confirmé
    Inscrit en
    Mars 2007
    Messages
    59
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 59
    Par défaut
    Citation Envoyé par laurentschneider
    Ujitsu ne nous a toujours pas donné sa version
    9.2.0.6

Discussions similaires

  1. Problème de left outer join avec Ibatis
    Par sarsipius dans le forum JDBC
    Réponses: 1
    Dernier message: 28/02/2008, 14h51
  2. left outer join avec condition
    Par fisto dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 14/08/2007, 08h52
  3. outer join avec access
    Par robocop2776 dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 24/07/2007, 15h43
  4. Outer join avec condition OR
    Par Ujitsu dans le forum Langage SQL
    Réponses: 1
    Dernier message: 28/03/2007, 23h08
  5. Réponses: 6
    Dernier message: 06/10/2006, 23h15

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