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 :

Besoin d'une requête récursive? [11gR2]


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 30
    Par défaut Besoin d'une requête récursive?
    Bonjour à tous,

    Je cherche un moyen de faire des requêtes Oracle récursives ou toute autre solution qui me permettrait d'accomplir la tâche suivante.

    En gros, j'ai une énorme séquence d'information constituée de données invalides que j'aimerais omettre de mon résultat. Ma "vraie" séquence est constituée de plusieurs milliers d'informations.

    À titre d'exemple, prenons la séquence réduite suivante: A7-X1-F6-X2-X3-C0-B1

    Cette séquence pourrait être modélisée dans ma base de données comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    WITH MaSequence AS
    (
    SELECT 'A7' AS CLE, 'X1' AS SUIVEUR, null AS PREDECESSEUR FROM dual union ALL
    SELECT 'X1'       , 'F6'           , 'A7'                 FROM dual union ALL
    SELECT 'F6'       , 'X2'           , 'X1'                 FROM dual union ALL
    SELECT 'X2'       , 'X3'           , 'F6'                 FROM dual union ALL
    SELECT 'X3'       , 'C0'           , 'X2'                 FROM dual union ALL
    SELECT 'C0'       , 'B1'           , 'X3'                 FROM dual union ALL
    SELECT 'B1'       , null           , 'C0'                 FROM dual
    )
    La colonne "CLE" est le nom de la clé courante.
    La colonne "SUIVEUR" est le nom de la clé suivant la clé courante.
    La colonne "PREDECESSEUR" est le nom de la clé précédant la clé courante.

    Dans ce modèle de données on défini comme "invalide" une clé débutant par la lettre "X".

    Note IMPORTANTE: Il ne faut absolument pas se fier à l'ordre des informations dans la table. Bref, même si dans mon exemple on peut croire que la colonne "CLE" est triée pour respecter une séquence, ce n'est en réalité absolument pas le cas.


    Donc, j'aimerais une façon d'omettre (sauter par dessus) les données invalides de façon à avoir le résultat suivant:

    CLE,SUIVEUR,PRÉDÉCESSEUR
    A7,F6,null
    F6,C0,A7
    C0,B1,F6
    B1,null,C0

  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
    Vous pouvez faire ainsi :
    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
    WITH MaSequence (clef) AS
    (
    SELECT 'A7' FROM dual union ALL
    SELECT 'X1' FROM dual union ALL
    SELECT 'F6' FROM dual union ALL
    SELECT 'X2' FROM dual union ALL
    SELECT 'X3' FROM dual union ALL
    SELECT 'C0' FROM dual union ALL
    SELECT 'B1' FROM dual
    )
    select clef
         , lead(clef) over(order by rownum asc) as suiveur
         , lag (clef) over(order by rownum asc) as predecesseur
      from MaSequence
     where clef not like 'X%';
     
    CLEF SUIVEUR PREDECESSEUR
    ---- ------- ------------
    A7   F6       -
    F6   C0      A7
    C0   B1      F6
    B1    -      C0

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 30
    Par défaut
    @Waldar:
    Malheureusement, ça ne peut pas fonctionner de cette façon, car selon ce que j'avais mentionné, il ne faut absolument pas se fier à l'ordre des informations dans ma table (mes "clefs" ne sont jamais triées en ordre de connexité, même si ma table "MaSequence" laisse présager le contraire).

    Bref, j'aimerais avoir le même résultat, même si les données de ma table était les suivantes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    (
    SELECT 'A7' AS CLE, 'X1' AS SUIVEUR, NULL AS PREDECESSEUR FROM dual union ALL
    SELECT 'C0'       , 'B1'           , 'X3'                 FROM dual union ALL
    SELECT 'F6'       , 'X2'           , 'X1'                 FROM dual union ALL
    SELECT 'X2'       , 'X3'           , 'F6'                 FROM dual union ALL
    SELECT 'X3'       , 'C0'           , 'X2'                 FROM dual union ALL
    SELECT 'X1'       , 'F6'           , 'A7'                 FROM dual union ALL
    SELECT 'B1'       , NULL           , 'C0'                 FROM dual
    )
    doit aussi donner

    CLE,SUIVEUR,PRÉDÉCESSEUR
    A7,F6,null
    F6,C0,A7
    C0,B1,F6
    B1,null,C0


    Pour y arriver, je ne vois pas d'autre moyen que d'utiliser une logique du genre:

    -Pour la clef courante, vérifier son suiveur (dans la colonne correspondante)
    -Prendre ce suiveur si différent de "X%", sinon
    -Vérifier le suiveur du suiveur de la clef courante et prendre ce suiveur si différent de "X%", sinon
    -Vérifier le suiveur du suiveur du suiveur... etc

    Même logique pour les prédécesseurs.

    En espérant que ce soit plus clair.

  4. #4
    Membre expérimenté
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Novembre 2013
    Messages
    144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Luxembourg

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Novembre 2013
    Messages : 144
    Par défaut START WITH / CONNECT BY
    Hello,

    Perso j'utiliserai la fonction START WITH / CONNECT BY

    Exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select level, CLE, PREDECESSEUR, SUIVEUR 
    from testtable2 
    start with PREDECESSEUR is null 
    connect by prior SUIVEUR = PREDECESSEUR;
    En prime le champ level qui t'indique la "profondeur" de connexion

  5. #5
    Membre Expert
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Par défaut
    Il faut faire une combinaison des propositions de easy-bi et de Waldar :

    1. Une étape de requête récursive qui "trie" les clés avec leur niveau.
    2. Puis utiliser lead et lag selon cet ordre.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 30
    Par défaut
    Génial! En combinant effectivement les deux approches, j'arrive au résultat désiré. Merci!!

    Par contre, lorsque j'applique votre solution sur mes vraies données, j'ai remarqué un petit problème que je peux reproduire avec la requête suivante:

    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
     
    WITH MaSequence AS
    (
      SELECT 'A7' AS CLE, 'X1' AS SUIVEUR, NULL AS PREDECESSEUR FROM dual union ALL
      SELECT 'C0'       , 'B1'           , 'X3'                 FROM dual union ALL
      SELECT 'F6'       , 'X2'           , 'X1'                 FROM dual union ALL
      SELECT 'X2'       , 'X3'           , 'F6'                 FROM dual union ALL
      SELECT 'X3'       , 'C0'           , 'X2'                 FROM dual union ALL
      SELECT 'X1'       , 'F6'           , 'A7'                 FROM dual union ALL
      SELECT 'X1'       , 'G6'           , 'A7'                 FROM dual union ALL
      SELECT 'G6'       , NULL           , 'X1'                 FROM dual union ALL
      SELECT 'B1'       , NULL           , 'C0'                 FROM dual
    )
    , OrderedSequence AS
    (
    SELECT level, CLE, PREDECESSEUR, SUIVEUR 
    FROM MaSequence 
      start WITH PREDECESSEUR IS NULL 
      connect BY prior SUIVEUR = CLE
    )
    SELECT cle
         , lead(cle) over(ORDER BY rownum ASC) AS suiveur
         , lag (cle) over(ORDER BY rownum ASC) AS predecesseur
    FROM OrderedSequence
    WHERE cle NOT LIKE 'X%'
    ;
    En gros, il y a un problème lorsque j'ai une clé qui a deux suiveurs (ex. "X1" a le suiveur "F6" et "G6"). Dans mon exemple le "connect by" semble se faire sur les champs "null" et me donne le résultat suivant:

    CLE SUIVEUR PREDECESSEUR
    --- ------- ------------
    A7  F6                   
    F6  C0      A7           
    C0  B1      F6           
    B1  G6      C0           
    G6          B1   
    alors que j'aimerais que le résultat soit:

    CLE SUIVEUR PREDECESSEUR
    --- ------- ------------
    A7  F6                   
    F6  C0      A7           
    C0  B1      F6           
    G6          B1
    C'est surement très faicle, mais je ne connais absolument pas la fonction "connect by"...

  7. #7
    Membre extrêmement actif
    Avatar de islamov2000
    Homme Profil pro
    Ingénieur d'études & developpement en informatique
    Inscrit en
    Septembre 2007
    Messages
    814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Ingénieur d'études & developpement en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2007
    Messages : 814
    Billets dans le blog
    6
    Par défaut Arborescence
    Citation Envoyé par Waldar Voir le message
    Vous pouvez faire ainsi :
    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
    WITH MaSequence (clef) AS
    (
    SELECT 'A7' FROM dual union ALL
    SELECT 'X1' FROM dual union ALL
    SELECT 'F6' FROM dual union ALL
    SELECT 'X2' FROM dual union ALL
    SELECT 'X3' FROM dual union ALL
    SELECT 'C0' FROM dual union ALL
    SELECT 'B1' FROM dual
    )
    select clef
         , lead(clef) over(order by rownum asc) as suiveur
         , lag (clef) over(order by rownum asc) as predecesseur
      from MaSequence
     where clef not like 'X%';
     
    CLEF SUIVEUR PREDECESSEUR
    ---- ------- ------------
    A7   F6       -
    F6   C0      A7
    C0   B1      F6
    B1    -      C0

    A partir de quel version on trouve lead et lag

  8. #8
    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 islamov2000 Voir le message

    A partir de quel version on trouve lead et lag
    Les fonctions analytiques (dont lead / lag) ont été introduites en 8i Enterprise Edition, mais démocratisées à partir de la 9i quand elles ont été utilisables par le plus grand nombre.

  9. #9
    Membre extrêmement actif
    Avatar de islamov2000
    Homme Profil pro
    Ingénieur d'études & developpement en informatique
    Inscrit en
    Septembre 2007
    Messages
    814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Ingénieur d'études & developpement en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2007
    Messages : 814
    Billets dans le blog
    6
    Par défaut successeur, prédécesseur de l'enregistrement
    Waldar
    lead et lag, c'est pour dire successeur, prédécesseur de l'enregistrement en cours.

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 30
    Par défaut
    Merci à tous pour votre aide!

    Malheureusement, le noeud du problème reste entier, car mes données dans ma table "MaSequence" ne sont pas triées et j'ai souvent des clés qui ont plusieurs suiveurs.

    Je vais ouvrir une autre discussion avec la même problématique, mais cette fois-ci, je vais demander de l'aide en PL/SQL. Selon les messages personnels que j'ai reçus, ça serait plus facile en PL/SQL, mais je ne connais pas ce langage...

    Voilà le lien: http://www.developpez.net/forums/d14...ive-omissions/

    À suivre!

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

Discussions similaires

  1. Besoin d'aide sur une requête récursive
    Par billybob2 dans le forum Développement
    Réponses: 5
    Dernier message: 05/02/2013, 09h54
  2. Besoin d'aide pour une requête récursive
    Par sqldeb dans le forum MS SQL Server
    Réponses: 0
    Dernier message: 30/11/2009, 17h05
  3. Obtenir la racine dans une requête récursive
    Par vingte dans le forum SQL
    Réponses: 2
    Dernier message: 24/08/2009, 12h49
  4. syntaxe d'une requête récursive
    Par dug dans le forum SQL
    Réponses: 3
    Dernier message: 18/06/2009, 17h58
  5. [SQL Server]Problème avec une requête récursive
    Par evans dans le forum Langage SQL
    Réponses: 3
    Dernier message: 05/04/2006, 20h16

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