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

PL/SQL Oracle Discussion :

Filtrage d'un arbre (tableau)


Sujet :

PL/SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Décembre 2006
    Messages
    255
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2006
    Messages : 255
    Par défaut Filtrage d'un arbre (tableau)
    Bonjour,

    voilà ça fait un petit moment que j'ai écrit une fonction PL/SQL qui génère un tableau (requête hiérarchique), qui est ensuite lu par du javascript (simplement transféré dans une variable) afin de générer un arbre HTML.

    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
    41
    42
    43
    44
    45
    46
    DECLARE
    	CURSOR cur IS
    	select op_id, 
    	op_descript,
    	op_id||' '||op_descript as description,
    	op_responsible,
    	op_veda_name,
    	op_begin,
    	op_end,
    	level,
    	CONNECT_BY_ISLEAF as leaf
    	from operations
    	connect by prior op_id = op_parent_op_id start with op_id = 9226;
    	levelPrec integer := 1;
    	wasLeaf boolean := false;
    	descr varchar2(500);    
    BEGIN
    	HTP.prn('[');
    	for c in cur loop
    		-- numbers of parents to close if level decrease
    		while ((levelPrec - c.level) > 0) loop
    			HTP.prn('],');
    			levelPrec := levelPrec - 1;
    			wasLeaf := false;
    		end loop;
    		-- if last item was a leaf, print a comma before the next one
    		if (wasLeaf) then
    			HTP.prn(',');
    		end if;
    		descr := translate(c.description,'''"','  ');
    		if (c.leaf = 0) then 
    			HTP.prn('["'||descr||'",0,');	
    			wasLeaf := false;
    		else
    			HTP.prn('["'||descr||'"]');
    			wasLeaf := true;
    		end if;
    		levelPrec := c.level;
    	end loop;
    	-- parents left to close
    	while (levelPrec > 1) loop
    		HTP.prn(']');
    		levelPrec := levelPrec - 1;
    	end loop;
    	HTP.p(']');
    END;
    Ca fonctionne parfaitement.

    Mais j'aimerais maintenant pouvoir filtrer l'arbre en fonction de la valeur de certain champs. J'ai naturellement essayé avec un WHERE dans la requête, mais celle-ci peut alors retourner des items de n'importe quel level (fils sans père etc...) et évidemment ça foire à la génération.

    J'ai donc essayé d'ajouter un if comme ceci :

    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    DECLARE
    	CURSOR cur IS
    	select op_id, 
    	op_descript,
    	op_id||' '||op_descript as description,
    	op_responsible,
    	op_veda_name,
    	op_begin,
    	op_end,
    	level,
    	CONNECT_BY_ISLEAF as leaf
    	from operations
    	connect by prior op_id = op_parent_op_id start with op_id = 9226;
    	levelPrec integer := 1;
    	wasLeaf boolean := false;
    	descr varchar2(500);    
    BEGIN
    	HTP.prn('[');
    	for c in cur loop
    		-- numbers of parents to close if level decrease
    		while ((levelPrec - c.level) > 0) loop
    			HTP.prn('],');
    			levelPrec := levelPrec - 1;
    			wasLeaf := false;
    		end loop;
    		-- if last item was a leaf, print a comma before the next one
    		if (wasLeaf) then
    			HTP.prn(',');
    		end if;
    		descr := translate(c.description,'''"','  ');
    		--if item have to be displayed
    		if (c.op_id like '%'||:P2_FILTRE_ID||'%' and upper(c.op_descript) like '%'||upper(:P2_FILTRE_DESCRIPTION)||'%' and upper(c.op_responsible) like '%'||upper(:P2_FILTRE_RESPONSABLE)||'%' and upper(c.op_veda_name) like upper(:P2_FILTRE_VEDA_NAME) and (c.op_begin > nvl(:P2_FILTRE_DATE_DEBUT,SYSDATE- numtoyminterval(60,'YEAR')) or c.op_begin is null) and (c.op_end < nvl(:P2_FILTRE_DATE_FIN,SYSDATE+1) or c.op_end is null)) then
    			if (c.leaf = 0) then 
    				HTP.prn('["'||descr||' t",0,');	
    				wasLeaf := false;
    			else
    				HTP.prn('["'||descr||' t"]');
    				wasLeaf := true;
    			end if;
    		else
    			if (c.leaf = 0) then 
    				HTP.prn('["'||descr||' f",0,');	
    				wasLeaf := false;
    			else
    				HTP.prn('["'||descr||' f"]');
    				wasLeaf := true;
    			end if;
    		end if;
    		levelPrec := c.level;
    	end loop;
    	-- parents left to close
    	while (levelPrec > 1) loop
    		HTP.prn(']');
    		levelPrec := levelPrec - 1;
    	end loop;
    	HTP.p(']');
    END;
    afin de génèrer le tableau complet mais en ajoutant à la fin de chaque item ' f' ou ' t' pour savoir si l'item doit être afficher ou non, ensuite je comptais enlever les items finissant par ' f' via javascript, mais ca fait 2 jours que je suis sur la fonction javascript et ça ne fonctionne pas. De plus il serait plus performant de générer directement le bon arbre avec le programme PL/SQL.

    Pour l'instant ça génère un tableau de la sorte (si je décide d'afficher que les élément dont l'id contient un 1) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [["9226 mesure ECOOL f",0,
     ["9227 mesure ECOOL f",0,
      ["9240 TD62 - Tracés au sol f"],
      ["10872 mesure ECOOL t",0,
       ["10873 mesure ECOOL t"]
      ],
     ],
     ["9228 TD68 f",0,
      ["9241 TD68 - Tracés au sol t"],
      ["10905 mesure ECOOL t",0,
       ["10906 mesure ECOOL t"]
      ]
     ]
    ]]
    Et il faudrait que ça génère directement ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    [
     ["10872 mesure ECOOL",0,
      ["10873 mesure ECOOL"]
     ],
     ["9241 TD68 - Tracés au sol"],
     ["10905 mesure ECOOL",0,
      ["10906 mesure ECOOL"]
     ]
    ]
    Dans la vraie vie ma table Opérations possède plus de 12 000 enregistrments donc l'arbre et bien plus gros.

    J'espère avoir été clair

    Merci pour votre aide, je suis dessus depuis la semaine dernière, et j'ai le cerveau qui s'enmèle, je ne sais plus quoi tenter :/

  2. #2
    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
    Houlala.. c'est compliqué ..
    Bon, j'ai peut être une idée :
    Est ce que tu peux utiliser le chemin (SYS_CONNECT_BY_PATH) pour avoir la liste des id ayant conduit à la ligne en cours ?
    Ensuite une condition sur l'existence d'un 1 dedans
    Ca donnerait (schématiquement)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT *
    FROM 
    ( SELECT SYS_CONNECT_BY_PATH(op_id,'-') as chemin, op_id, op_descript
    FROM .. CONECT BY ..)
    WHERE instr(chemin, '1') > 0
    Peut être que ça peut t'aider comme base pour ce que tu veux faire.

  3. #3
    Membre éclairé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Décembre 2006
    Messages
    255
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2006
    Messages : 255
    Par défaut
    Merci pour la réponse, à vrai dire je ne pensais même pas en avoir une
    Car c'est vrai que c'est compliqué pour quelqu'un qui n'a pas suivi depuis le début de se mettre dans le bain.

    J'avais totalement oublié SYS_CONNECT_BY_PATH, je peux peut-être faire quelquechose avec en effet. Mais le filtrage peut être fait sur tous les champs de la table (op_id, op_descript, op_responsible, op_veda_name, op_begin, op_end) et pas seulement sur l'id. Il me faudra donc un SYS_CONNECT_BY_PATH pour chaque champs.
    Je vais étudier ça

    Perso je pensais plutôt modifier le 2ème programme que j'ai indiqué, notamment le else (ligne 40, si l'item ne doit pas être afficher), en décrémentant le level de 1 juste le temps qu'il faut (jusqu'à ce qu'on repasse à un noeud du même level que le noeud qui n'a pas été affiché).

    Car en gros le fonctionnement c'est si un noeud n'est pas affiché, ses enfants deviennent les enfants du père du noeud qui n'est pas affiché. Ca revient à décrémenter le level de 1 pour tous les enfants (et les sous-enfants etc...) je pense. Je ne sais pas si je suis clair

  4. #4
    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
    Si si, ta dernière phrase est super claire.
    Par contre, comment réaliser une modification d'arbre en supprimant juste des noeuds, et en requête, je crains de ne pouvoir t'aider.

    Moi ce que je ferais c'est insérer le résultat de ta requête d'arbre dans une collection, et la retraiter ensuite.

  5. #5
    Membre éclairé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Décembre 2006
    Messages
    255
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2006
    Messages : 255
    Par défaut
    C'est ce que je fait pour l'instant, je place le resultat complet de la requete dans un tableau (en ajoutant ' f' pour false ou ' t' pour true au nom de l'item pour savoir si je devrai le retirer ou non).

    Puis j'ai une fonction javascript qui retire tous les éléments finissants par ' f' (ainsi que l'élément 0 associé), attention ça pique les yeux :

    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
     
    function recur(arr){
    	for(var k=0;k<arr.length;k++){
    		if (typeof arr[k] == "string") {
    			if (/ f$/.test(arr[k])) {
    				arr.splice(k,1);
    				if (arr[k] == 0) 
    					arr.splice(k--,1);
    			}
    		}
    		else {
    			new recur(arr[k]);
    			if (arr[k].length == 0)
    				arr.splice(k,1);
    		}
    	}
    }
    Le problème là c'est qu'après traitement il me reste des tableaux vides, ou du moins inutiles.

    Par exemple j'obtiens ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    '[[[["10872 mesure ECOOL t",0,["10873 mesure ECOOL t"]]],[["9241 TD68 - Tracés au sol t"],["10905 mesure ECOOL t",0,["10906 mesure ECOOL t"]]]]]'
    au lieu de ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    '[["10872 mesure ECOOL t",0,["10873 mesure ECOOL t"]],["9241 TD68 - Traces au sol t"],["10905 mesure ECOOL t",0,["10906 mesure ECOOL t"]]]'
    Donc la fonction qui construit l'arbre HTML n'aime pas les tableaux en trop. Et je ne vois pas du tout comment supprimer les tableaux redondants...

  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
    Bon, tu vas m'obliger à le coder
    Je te tiens au courant d'ici ce soir.

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

Discussions similaires

  1. [Toutes versions] Filtrage automatique d'un tableau
    Par kyasteph dans le forum Excel
    Réponses: 3
    Dernier message: 18/10/2013, 19h03
  2. [XL-2007] Filtrage multiple d'un tableau excel avec macro
    Par robby98800 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 29/05/2012, 09h39
  3. Filtrage d'un Tableau et Variables
    Par TD_RTM dans le forum Mode d'emploi & aide aux nouveaux
    Réponses: 1
    Dernier message: 22/08/2006, 13h54
  4. Un arbre dans un tableau
    Par Oberown dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 01/08/2006, 10h12
  5. XSL pour visualiser arbre XML sous forme de tableau en HTML
    Par mattmat dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 28/03/2003, 10h55

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