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 :

Requête hiérarchique avec même état


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Septembre 2004
    Messages
    378
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 378
    Par défaut Requête hiérarchique avec même état
    Bonjour,

    J'ai une table qui contient des dossiers avec une référence sur elle-même car un dossier peut être le père d'un ou plusieurs fils (un fils n'ayant qu'un seul père). Ce qui est représenté par un colonne ID et une autre ID_PERE.

    Je dois extraire tous les dossiers clos. Si un dossier a des fils ou est le père de fils, il faut que tous les dossiers soient clos. Si un seul de ces dossiers n'est pas clos, on n'extraie rien.

    Je n'arrive pas à faire ça avec une requête. Je me dis que ça doit être faisable avec une fonction analytique mais comme je ne connais pas, j'ai besoin de votre aide.

    Merci.

  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 : 48
    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
    Regardez plutôt du côté de la syntaxe CONNECT BY

  3. #3
    Membre éclairé
    Inscrit en
    Septembre 2004
    Messages
    378
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 378
    Par défaut
    Merci.
    J'avais commencé à chercher dans ce sens mais je n'arrive pas à n'extraire que lorsque tous les dossiers liés sont terminé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select *
    from dossier
    where ETAT_DOSSIER = 'TERMINE'
    connect by prior ID_DOSSIER = ID_DOSSIER_PERE
    start with ID_DOSSIER_PERE is null
    Par exemple, j'ai un dossier père qui est terminé et qui a 3 fils dont 1 est ouvert.
    Cette requête me retourne 3 lignes : le père et les 2 fils terminé
    Mais dans ce cas, je veux que la requête ne retourne rien car un des dossiers liés n'est pas terminé.

  4. #4
    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
    Tu vas être obligé de passer par 1ère requête hiérarchique sans filtre sur le statut, puis de faire à partir de ce résultat un filtre sur les objets ayant le même père mais qui n'ont pas le même statut ...

    EDIT : ça peut donner quelque chose du genre :

    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
     
    WITH dossier AS
    ( SELECT 1 AS ID_DOSSIER, NULL AS ID_DOSSIER_PERE, 'T' AS ETAT_DOSSIER FROM DUAL
      UNION ALL
      SELECT 11 AS ID_DOSSIER, 1 AS ID_DOSSIER_PERE, 'T' AS ETAT_DOSSIER FROM DUAL
      UNION ALL
      SELECT 12 AS ID_DOSSIER, 1 AS ID_DOSSIER_PERE, 'T' AS ETAT_DOSSIER FROM DUAL
      UNION ALL
      SELECT 2 AS ID_DOSSIER, NULL AS ID_DOSSIER_PERE, 'T' AS ETAT_DOSSIER FROM DUAL
      UNION ALL
      SELECT 21 AS ID_DOSSIER, 2 AS ID_DOSSIER_PERE, 'T' AS ETAT_DOSSIER FROM DUAL
      UNION ALL
      SELECT 22 AS ID_DOSSIER, 2 AS ID_DOSSIER_PERE, 'E' AS ETAT_DOSSIER FROM DUAL
    )
    SELECT id_dossier, id_dossier_pere, etat_dossier FROM (
    SELECT d2.id_dossier, d2.id_dossier_pere, d2.etat_dossier, d2.id_root
          ,MIN(DECODE(ETAT_DOSSIER,'T',1,0)) OVER (PARTITION BY ID_ROOT) AS MIN_ETAT_DOSSIER
      FROM
        (
        SELECT d.id_dossier, d.id_dossier_pere, d.etat_dossier
              ,CONNECT_BY_ROOT ID_DOSSIER AS ID_ROOT
            FROM dossier d
        --WHERE ETAT_DOSSIER = 'T'
        connect BY prior ID_DOSSIER = ID_DOSSIER_PERE
        start WITH ID_DOSSIER_PERE IS NULL
        ) d2
       )
    WHERE min_etat_dossier = 1

  5. #5
    Membre éclairé
    Inscrit en
    Septembre 2004
    Messages
    378
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 378
    Par défaut
    Merci bien.

    J'avais trouvé une solution un peu différente. Mais la mienne m'a l'air un peu plus lourde.
    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
    WITH dossier AS
    ( SELECT 1 AS ID_DOSSIER, NULL AS ID_DOSSIER_PERE, 'T' AS ETAT_DOSSIER FROM DUAL
      UNION ALL
      SELECT 11 AS ID_DOSSIER, 1 AS ID_DOSSIER_PERE, 'T' AS ETAT_DOSSIER FROM DUAL
      UNION ALL
      SELECT 12 AS ID_DOSSIER, 1 AS ID_DOSSIER_PERE, 'T' AS ETAT_DOSSIER FROM DUAL
      UNION ALL
      SELECT 2 AS ID_DOSSIER, NULL AS ID_DOSSIER_PERE, 'T' AS ETAT_DOSSIER FROM DUAL
      UNION ALL
      SELECT 21 AS ID_DOSSIER, 2 AS ID_DOSSIER_PERE, 'T' AS ETAT_DOSSIER FROM DUAL
      UNION ALL
      SELECT 22 AS ID_DOSSIER, 2 AS ID_DOSSIER_PERE, 'E' AS ETAT_DOSSIER FROM DUAL
    )
    select ID_DOSSIER, ID_DOSSIER_PERE , ETAT_DOSSIER , tot_doss_lies, tot_doss_clos
    from (
    select ID_DOSSIER, ID_DOSSIER_PERE , ETAT_DOSSIER
    , count(*) over (partition by ID_DOSSIER_PERE) tot_doss_lies
    , count(*) over (partition by ID_DOSSIER_PERE, ETAT_DOSSIER) tot_doss_clos
    from (
    select ID_DOSSIER, NVL(ID_DOSSIER_PERE, ID_DOSSIER) ID_DOSSIER_PERE, ETAT_DOSSIER
    from dossier
    start with ID_DOSSIER_PERE is null
    connect by prior ID_DOSSIER = ID_DOSSIER_PERE 
    order by 1, ETAT_DOSSIER
    )
    )
    where tot_doss_lies=tot_doss_clos;

  6. #6
    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
    Et il faut rajouter une condition sur l'état du dossier final ; le nom "tot_dossier_clos" prête à confusion, il s'agit en fait du nombre de dossiers ayant le même statut. Un père avec tous les fils ayant un statut autre que Terminé serait sélectionné.

  7. #7
    Membre éclairé
    Inscrit en
    Septembre 2004
    Messages
    378
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 378
    Par défaut
    Oui très juste.
    C'est pour ça que je préfère ta solution
    Merci bien.

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

Discussions similaires

  1. Mettre 2 requêtes dans 1 même état
    Par Boubas1 dans le forum IHM
    Réponses: 14
    Dernier message: 17/01/2008, 17h43
  2. Réponses: 5
    Dernier message: 13/04/2007, 15h14
  3. Réponses: 7
    Dernier message: 29/03/2007, 16h30
  4. Réponses: 8
    Dernier message: 13/09/2006, 18h21
  5. [SQL] Requête complexe avec appel multiple à la même table
    Par Julien Dufour dans le forum Langage SQL
    Réponses: 9
    Dernier message: 14/04/2005, 15h12

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