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 :

Requete un peu complexe avec la fonction IN


Sujet :

Oracle

  1. #21
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    déjà je remplace :

    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
      AND ( EXISTS (SELECT  NULL
                                    FROM s23_subscriber_changes s23sc,
                                    s23_call_alloc_run_nos s23rn
                                    WHERE s23rn.pt_partition = 1
                            AND s23sc.cust_number = s23ub.cust_number
                            AND s23sc.s23_subscriber = s23ub.cust_number
                                    AND s23sc.pt_partition = s23rn.pt_partition)
     
                     OR EXISTS (SELECT NULL
                                FROM s23_subscriber_changes s23sc1,
                                               s23_call_alloc_run_nos s23rn1
                                               WHERE s23rn1.pt_partition = 1
                                    AND s23ub.usag_id  = s23sc1.subc_new_usag_id
                                               AND s23sc1.pt_partition = s23rn1.pt_partition)
                      );
    par :

    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
    AND EXISTS 
        ( SELECT  NULL
            FROM s23_subscriber_changes s23sc,
                 s23_call_alloc_run_nos s23rn
           WHERE s23rn.pt_partition = 1
             AND s23sc.cust_number = s23ub.cust_number
             AND s23sc.s23_subscriber = s23ub.cust_number
             AND s23sc.pt_partition = s23rn.pt_partition
           UNION
          SELECT  NULL
            FROM s23_subscriber_changes s23sc,
                 s23_call_alloc_run_nos s23rn
           WHERE s23rn.pt_partition = 1
             AND s23ub.usag_id  = s23sc1.subc_new_usag_id
             AND s23sc1.pt_partition = s23rn1.pt_partition)
        )

  2. #22
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    et :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    AND EXISTS
        ( SELECT NULL
            FROM s23_usage s23u
            WHERE s23u.pt_partition = 1 AND s23u.s23_at_key = s23ub.s23_at_key
          AND s23ub.usag_id = s23u.usag_id
            AND ( s23u.subr_at_swoff >= ( SELECT add_months(cc.cust_next_inv_date,to_number(substr(cc.cust_bill_key,1,2))*-1)
                                            FROM ftrprod_us1.co_customers cc
                                           WHERE cc.cust_number = s23u.cust_number
                                         )
                         OR s23u.subr_at_swoff = to_date('17-NOV-1858', 'DD-MON-YYYY') 
                )
         )
    devient :

    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
    AND EXISTS
        ( SELECT NULL
            FROM s23_usage s23u,ftrprod_us1.co_customers cc
            WHERE s23u.pt_partition = 1 
              AND s23u.s23_at_key = s23ub.s23_at_key
              AND s23ub.usag_id = s23u.usag_id
              AND s23u.subr_at_swoff >= add_months(cc.cust_next_inv_date,to_number(substr(cc.cust_bill_key,1,2))*-1)
              AND cc.cust_number = s23u.cust_number 
            UNION
           SELECT NULL
            FROM s23_usage s23u
            WHERE s23u.pt_partition = 1 
              AND s23u.s23_at_key = s23ub.s23_at_key
              AND s23ub.usag_id = s23u.usag_id
              AND s23u.subr_at_swoff = to_date('17-NOV-1858', 'DD-MON-YYYY')  
         )
    Pourrais-tu essayé :

    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
    UPDATE S23_USE_BREAKDOWN S23UB
    SET
    S23UB.SUBR_AT_CALLS=0, S23UB.SUBR_AT_DURATION=0,
    S23UB.SUBR_AT_UNITS=0, S23UB.SUBR_AT_VOLUME=0,
    S23UB.SUBR_AT_COSTIC=0, S23UB.SUBR_AT_COSTWS=0,
    S23UB.SUBR_AT_COSTRT=0, S23UB.SUBR_AT_COSTDC=0
    WHERE s23ub.pt_partition = 1
    AND EXISTS
        ( SELECT NULL
            FROM s23_usage s23u,ftrprod_us1.co_customers cc
            WHERE s23u.pt_partition = 1 
              AND s23u.s23_at_key = s23ub.s23_at_key
              AND s23ub.usag_id = s23u.usag_id
              AND s23u.subr_at_swoff >= add_months(cc.cust_next_inv_date,to_number(substr(cc.cust_bill_key,1,2))*-1)
              AND cc.cust_number = s23u.cust_number 
            UNION
           SELECT NULL
            FROM s23_usage s23u
            WHERE s23u.pt_partition = 1 
              AND s23u.s23_at_key = s23ub.s23_at_key
              AND s23ub.usag_id = s23u.usag_id
              AND s23u.subr_at_swoff = to_date('17-NOV-1858', 'DD-MON-YYYY')  
         ) 
    AND EXISTS 
        ( SELECT  NULL
            FROM s23_subscriber_changes s23sc,
                 s23_call_alloc_run_nos s23rn
           WHERE s23rn.pt_partition = 1
             AND s23sc.cust_number = s23ub.cust_number
             AND s23sc.s23_subscriber = s23ub.cust_number
             AND s23sc.pt_partition = s23rn.pt_partition
           UNION
          SELECT  NULL
            FROM s23_subscriber_changes s23sc,
                 s23_call_alloc_run_nos s23rn
           WHERE s23rn.pt_partition = 1
             AND s23ub.usag_id  = s23sc1.subc_new_usag_id
             AND s23sc1.pt_partition = s23rn1.pt_partition)
        )  
    ;
    OR UNION

  3. #23
    Rédacteur

    Inscrit en
    Septembre 2004
    Messages
    626
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 626
    Points : 848
    Points
    848
    Par défaut
    Personnellement j'opterais plutôt pour le OR dans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    EXISTS ( 
       SELECT ...
       UNION
       SELECT ...
    )
    je le transformerais en :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    (
       EXISTS ( 
          SELECT ...
       )
       OR
       EXISTS (
          SELECT ...
       )
    )
    car pour chaque ligne des deux select qui convient, on renvoie NULL avant de faire l'union. En plus l'union va faire un tri pour éliminer les doublons (ok c'est des null qui sont renvoyés).

    Avec un peu de chance, Oracle va lancer les deux select du OR en parallèle et s'arrêter dès que l'un d'entre eux a renvoyé une ligne.


    Laly.

  4. #24
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    UNION ALL à la place de l'UNION effectivement... sinon... le OR doit être remplacer par l'UNION ALL... ça fait partie des bonnes pratiques de dév

  5. #25
    Rédacteur

    Inscrit en
    Septembre 2004
    Messages
    626
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 626
    Points : 848
    Points
    848
    Par défaut
    Moi je testerais quand même avec le OR car sinon le EXISTS ne sera appliqué qu'après le UNION ALL alors qu'on ne cherche l'existence que d'une ligne vérifiant l'un ou l'autre des critères. A voir


    Laly.

  6. #26
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    Explication :

    soit :
    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
    SQL> create table t1 ( a int, b char(2000) );
    Table created.
     
    SQL> create table t2 ( a int, b char(2000) );
    Table created.
     
    SQL> create index t1_idx on t1(a);
    Index created.
     
    SQL> create index t2_idx on t2(a);
    Index created.
     
    SQL> exec dbms_stats.set_table_stats( user, 'T1', 
    numRows => 10000000, numBlks => 5000000 );
     
    PL/SQL procedure successfully completed.
     
    SQL> exec dbms_stats.set_table_stats( user, 'T2', 
    numRows => 10000000, numBlks => 5000000 );
     
    PL/SQL procedure successfully completed.
    Voila les 2 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
    SQL>explain plan 
      2  set statement_id = 'X' 
      3  into plan_table for
      4  select t1.a from t1,t2
      5     where t1.a = t2.B
      6            or  t2.a = t1.b
      7  --      UNION ALL
      8    --    select t2.a from t1,t2
      9   --where t1.b = t2.a
     10  ;
    SQL>select LPAD(' ',2*(LEVEL-1))||operation  "OPERATION",
      2   options     "TYPE_ACCES",
      3   DECODE(TO_CHAR(id),'0','COST= '|| NVL(TO_CHAR(position),'Indefini'), object_name) "NOM_OBJET",
     
      4   id || '-' || NVL(parent_id,0) || '-' || NVL(position,0) "ORDRE",
      5   ' COUT=' || COST ||','||'Card=' || CARDINALITY "Cout Op"
      6  From plan_table
      7  start with id = 0
      8  and statement_id = 'X'
      9  connect by prior id = parent_id
     10  and statement_id = 'X';
     
    OPERATION                                     TYPE_ACCES           NOM_OBJET                      ORDRE    
    --------------------------------------------- -------------------- ------------------------------ --
    SELECT STATEMENT                                                   COST= 2233640                  0-0-2233 
                                                                                                      640
     
      CONCATENATION                                                                                   1-0-1    
        MERGE JOIN                                                                                    2-1-1    
          TABLE ACCESS                            BY INDEX ROWID       T2                             3-2-1    
            INDEX                                 FULL SCAN            T2_IDX                         4-3-1    
          SORT                                    JOIN                                                5-2-2    
            TABLE ACCESS                          FULL                 T1                             6-5-1    
        MERGE JOIN                                                                                    7-1-2    
          TABLE ACCESS                            BY INDEX ROWID       T1                             8-7-1    
            INDEX                                 FULL SCAN            T1_IDX                         9-8-1    
          FILTER                                                                                      10-7-2   
            SORT                                  JOIN                                                11-10-1  
              TABLE ACCESS                        FULL                 T2                             12-11-1
    et :

    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
    SQL>delete from plan_table where statement_id = 'X';
    SQL>explain plan 
      2  set statement_id = 'X' 
      3  into plan_table for
      4  select t1.a from t1,t2
      5     where t1.a = t2.B
      6          --  or  t2.a = t1.b
      7        UNION ALL
      8        select t2.a from t1,t2
      9   where t1.b = t2.a
     10  ;
    SQL>select LPAD(' ',2*(LEVEL-1))||operation  "OPERATION",
      2   options     "TYPE_ACCES",
      3   DECODE(TO_CHAR(id),'0','COST= '|| NVL(TO_CHAR(position),'Indefini'), object_name) "NOM_OBJET",
     
      4   id || '-' || NVL(parent_id,0) || '-' || NVL(position,0) "ORDRE",
      5   ' COUT=' || COST ||','||'Card=' || CARDINALITY "Cout Op"
      6  From plan_table
      7  start with id = 0
      8  and statement_id = 'X'
      9  connect by prior id = parent_id
     10  and statement_id = 'X';
     
    OPERATION                                     TYPE_ACCES           NOM_OBJET                      ORDRE   
    --------------------------------------------- -------------------- ------------------------------ --
    SELECT STATEMENT                                                   COST= 2232040                  0-0-2232
                                                                                                      040
     
      UNION-ALL                                                                                       1-0-1   
        MERGE JOIN                                                                                    2-1-1   
          INDEX                                   FULL SCAN            T1_IDX                         3-2-1   
          SORT                                    JOIN                                                4-2-2   
            TABLE ACCESS                          FULL                 T2                             5-4-1   
        MERGE JOIN                                                                                    6-1-2   
          INDEX                                   FULL SCAN            T2_IDX                         7-6-1   
          SORT                                    JOIN                                                8-6-2   
            TABLE ACCESS                          FULL                 T1                             9-8-1

  7. #27
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    je t'accorde que la différence de coût sur l'exemple n'est pas significative mais c'est une bonne habitude à prendre

    En revanche, je ne trouve plus l'article où j'ai lu ça :'([/quote]

  8. #28
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 075
    Points
    19 075
    Par défaut
    au fait : http://download-west.oracle.com/docs/cd/B10501_01/em.920/a86647/vmqtune.htm#1004143

    C'est surtout NOT IN qui doit être remplacé en NOT EXISTS... autant pour moi... je pensais que le IN devait systématiquement être remplacé par EXISTS alors que c'est surtout le cas si c'est précédé de NOT

    c'est Oracle qui le dit

    Pour répondre au fait que IN existe toujours : c'est pour assurer la compatibilité ascendante

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 0
    Dernier message: 23/06/2011, 11h28
  2. requete SQl avec la fonction max () qui ne marche pas
    Par eclipse012 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 09/11/2006, 14h32
  3. Problème avec la fonction créer requete de la FAQ
    Par greg64 dans le forum Access
    Réponses: 8
    Dernier message: 28/03/2006, 12h28
  4. Réponses: 2
    Dernier message: 02/12/2005, 10h53
  5. [Requete SQL en VBA] Problème avec la fonction FLOOR
    Par zubral dans le forum Langage SQL
    Réponses: 4
    Dernier message: 13/07/2004, 13h24

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