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 :

concaténation des status d'un détail sur une ligne


Sujet :

Oracle

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut concaténation des status d'un détail sur une ligne
    Bonjour,

    J'essaye désespérément de faire qulequechose qui doit être simple pour qui manipule les datawarehouses mais je ne m'en sors pas.

    Exemple :
    tab_maitre

    id status flag
    1 x Y
    2 x Y
    3 x N
    tab_fille
    id id_maitre status
    1 1 a
    2 1 b
    3 1 c
    4 2 a
    5 2 b
    6 3 a
    je veux mettre à jour la colonne status de tab_maitre où le flag est à 'Y' avec la concaténation des status du fils.

    Je voudrais donc :
    tab_maitre

    id status flag
    1 abc Y
    2 ab Y
    3 x N
    j'ai 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
    SELECT id_maitre, rems
      FROM (SELECT   id_maitre, rems, MAX (LENGTH (rems))
                FROM (SELECT e.id_maitre,
                                   LEAD (r.status, 1) OVER (ORDER BY r.id_maitre)
                                || ' ' || LEAD (r.status, 2) OVER (ORDER BY r.id_maitre)
                                || ' ' || LEAD (r.status, 3) OVER (ORDER BY r.id_maitre)
                                || ' ' || LEAD (r.status, 4) OVER (ORDER BY r.id_maitre)
                                || ' ' || LEAD (r.status, 5) OVER (ORDER BY r.id_maitre)
                                || ' ' || LEAD (r.status, 6) OVER (ORDER BY r.id_maitre)
                                                                             rems
                          FROM tab_fils e,
                               tab_maitre r
                         WHERE e.status_flag = 'Y'
                           AND e.id_maitre = r.id_maitre
                      ORDER BY 1)
            GROUP BY id_maitre, rems)
    ;
    mais :
    - le résultat semble faux
    - les perfs sont pas terribles
    - je ne connais pas le nombre de fils donc là j'ai été jusqu'à 6 mais rien ne me dit que ça suffit

    Bref, voila un problème bien épineux et je vous serais très reconnaissant de me donner un coup de main

  2. #2
    Membre régulier Avatar de thanaos
    Inscrit en
    Mai 2006
    Messages
    94
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 94
    Points : 76
    Points
    76
    Par défaut
    Bonjour Fred.
    Désolé pour la perturbation, mais essayant de comprendre ton code, je m'étonne de l'abscence d'une relation par CONNECT BY PRIOR dans ta requête. Elle n'est pas exploitable ici ?
    --------------------------------------------------------------------------
    Je suis aveugle. Eclairez moi de votre lumière.
    Apache2 / PHP5.4 / MySQL 5/ Win7/RedHat

  3. #3
    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
    Salut Orafrance,


    Tu peux essayer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    update  TAB_MAITRE a
    set     status = (
              select max(decode(rn, 1, status)) || max(decode(rn, 2, status)) || max(decode(rn, 3, status)) || max(decode(rn, 4, status)) || max(decode(rn, 5, status)) status 
              from         
                (                    
                  select  id_maitre, row_number() over(partition  by id_maitre order by id) rn, status 
                  from   tab_fille b
                )
              where id_maitre = id 
              group by id_maitre
            )
    Ca a l'air de bien marcher, mais on suppose qu'il y aura maximum N status dans la table tab_fille...
    Et au niveau du plan, je n'ai pas l'impression que le prédicate filtrant sur l'id du père est "pushé" à l'intérieur de la view online...

    Sinon, si tu es en 9i+, tu peux regarder au niveau des fonctions d'aggrégat définie par l'utilisateur.


    Laly.
    In the heart of the truly greats, perfection is never achieved but endlessly pursued.

    Mon article sur les fonctions analytiques d'Oracle (calcul de moyennes mobiles, de quartiles et bien d'autres...)

  4. #4
    Inactif   Avatar de Médiat
    Inscrit en
    Décembre 2003
    Messages
    1 946
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 946
    Points : 2 227
    Points
    2 227
    Par défaut
    Fred regarde là : http://www.developpez.net/forums/sho...d.php?p=311475.

    Il y a un exemple sous ORACLE qui correspond à ce que tu veux faire...
    J'affirme péremptoirement que toute affirmation péremptoire est fausse
    5ième élément : barde-prince des figures de style, duc de la synecdoque
    Je ne réponds jamais aux questions techniques par MP

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    Citation Envoyé par thanaos
    Bonjour Fred.
    Désolé pour la perturbation, mais essayant de comprendre ton code, je m'étonne de l'abscence d'une relation par CONNECT BY PRIOR dans ta requête. Elle n'est pas exploitable ici ?
    j'y avais bien pensé mais j'arrive pas à m'en sortir

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    Citation Envoyé par Médiat
    Fred regarde là : http://www.developpez.net/forums/sho...d.php?p=311475.

    Il y a un exemple sous ORACLE qui correspond à ce que tu veux faire...
    en effet, c'est exactement ça

    je regarde ça de suite

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    pour info, le plan de test est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    create table tab_maitre(id number, remarks varchar2(200), remarks_flag varchar2(1) default 'N');
    create table tab_fils(id number, id_maitre number,remarks varchar2(200));
     
    insert into tab_maitre values (1,'x','Y');
    insert into tab_maitre values (2,'x','Y');
    insert into tab_maitre values (3,'x','N');
     
    insert into tab_fils values (1,1,'a');
    insert into tab_fils values (2,1,'b');
    insert into tab_fils values (3,1,'c');
    insert into tab_fils values (4,1,'d');
    insert into tab_fils values (5,2,'e');
    insert into tab_fils values (6,2,'f');
    insert into tab_fils values (7,3,'g');
    Et voila qui marche presque :
    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
    SELECT id_maitre, substr(Liste ,2) rems
    FROM (SELECT id_maitre, remarks, PRIOR remarks, LEVEL AS niveau, sys_connect_by_path(remarks, ' ') AS Liste 
          FROM tab_fils a 
          where  id_maitre IN (select id_maitre from tab_maitre where remarks_flag = 'Y')
          CONNECT BY id_maitre = PRIOR id_maitre AND remarks > PRIOR remarks 
          START WITH (id_maitre, remarks) IN (SELECT id_maitre, Min(remarks) FROM tab_fils GROUP BY id_maitre) 
         ) b 
    WHERE niveau = (SELECT Max(Niveau) 
                    FROM (SELECT id_maitre, remarks, PRIOR remarks, LEVEL AS niveau, sys_connect_by_path(remarks, ',') AS Liste 
                          FROM tab_fils a 
          								where  id_maitre IN (select id_maitre from tab_maitre where remarks_flag = 'Y')
                           CONNECT BY id_maitre = PRIOR id_maitre AND remarks > PRIOR remarks 
                          START WITH (id_maitre, remarks) IN (SELECT id_maitre, Min(remarks) FROM tab_fils GROUP BY id_maitre) 
                         ) a 
                    WHERE a.id_maitre = b.id_maitre 
                   );
    ID_MAITRE REMS
    ---------- -------------------------------
    1 a b c d
    2 e f
    3 g
    ça force le respect

    le problème c'est sur ID 3 qui devrait donner 'x', je ne devrais même pas le traiter

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    c'est réglé

    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
    SELECT id_maitre, substr(Liste ,2) rems
    FROM (SELECT id_maitre, remarks, PRIOR remarks, LEVEL AS niveau, sys_connect_by_path(remarks, ' ') AS Liste 
          FROM tab_fils a ,tab_maitre tm
          WHERE a.id_maitre = tm.id and tm.remarks_flag = 'Y'     
          where  id_maitre IN (select id_maitre from tab_maitre where remarks_flag = 'Y')
          CONNECT BY id_maitre = PRIOR id_maitre AND remarks > PRIOR remarks 
          START WITH (id_maitre, remarks) IN (SELECT id_maitre, Min(remarks) FROM tab_fils GROUP BY id_maitre) 
         ) b 
    WHERE niveau = (SELECT Max(Niveau) 
                    FROM (SELECT id_maitre, remarks, PRIOR remarks, LEVEL AS niveau, sys_connect_by_path(remarks, ',') AS Liste 
                          FROM tab_fils a 
          								where  id_maitre IN (select id_maitre from tab_maitre where remarks_flag = 'Y')
                           CONNECT BY id_maitre = PRIOR id_maitre AND remarks > PRIOR remarks 
                          START WITH (id_maitre, remarks) IN (SELECT id_maitre, Min(remarks) FROM tab_fils GROUP BY id_maitre) 
                         ) a 
                    WHERE a.id_maitre = b.id_maitre 
                   );

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    j'suis passé d'un coût de 3000 à 7 en utilisant IN au lieu de la jointure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    FROM tab_fils a ,tab_maitre tm
          WHERE a.id_maitre = tm.id and tm.remarks_flag = 'Y'
    devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    FROM tab_fils a 
          WHERE a.id_maitre IN (SELECT id FROM tab_maitre tm WHERE tm.remarks_flag = 'Y'

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    Finalement ceci suffit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT id_maitre, liste
      FROM (SELECT id_maitre, liste, niveau,
                   MAX (niveau) OVER (PARTITION BY id_maitre) max_niv
              FROM (SELECT     id_maitre, remarks, LEVEL AS niveau,
                               SYS_CONNECT_BY_PATH (remarks, ' ') AS liste
                          FROM tab_fils a
                         WHERE id_maitre IN (SELECT id
                                               FROM tab_maitre
                                              WHERE remarks_flag = 'Y')
                    CONNECT BY id_maitre = PRIOR id_maitre
                               AND remarks > PRIOR remarks))
     WHERE niveau = max_niv

  11. #11
    Inactif   Avatar de Médiat
    Inscrit en
    Décembre 2003
    Messages
    1 946
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 946
    Points : 2 227
    Points
    2 227
    Par défaut
    Fred j'ai utilisé ton idée de la fonction analytique pour simplifier la requête qui se trouve là : http://www.developpez.net/forums/sho...d.php?p=311475.

    Merci et
    J'affirme péremptoirement que toute affirmation péremptoire est fausse
    5ième élément : barde-prince des figures de style, duc de la synecdoque
    Je ne réponds jamais aux questions techniques par MP

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    par contre, dans mon exemple les perfs sont catastrophiques :'(

    je vais voir comment m'en sortir

    Sinon, bravo pour l'utilisation du MAX analytique

Discussions similaires

  1. Réponses: 3
    Dernier message: 15/02/2011, 17h17
  2. Réponses: 9
    Dernier message: 04/04/2007, 11h16
  3. Méthode FIFO sur une ligne détail
    Par Aitone dans le forum SAP Crystal Reports
    Réponses: 7
    Dernier message: 30/11/2006, 18h17
  4. détail sur une ligne
    Par zut94 dans le forum SAP Crystal Reports
    Réponses: 1
    Dernier message: 19/09/2006, 11h45
  5. [CRXI] Détail sur une ligne
    Par Julyon dans le forum SAP Crystal Reports
    Réponses: 1
    Dernier message: 21/08/2006, 14h03

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