Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Autojointure : Sélection récursive.

15 réponses
Avatar
Damran
Bonjour
J'ai un petit problème.
Pour représenter des articles présent dans un niveau, j'ai un ID_PERE qui
représente donc où est attaché mon article.
Je voudrais à partir d'un niveau, récupérer tous les articles présent en
dessous de ce niveau et ce, quelques soit le nombre de sous niveau.
J'ai beau chercher, j'ai l'impression que c'est impossible en une seule
requête.
Haa là là, si la base utilisait la représentation intervallaire, je n'aurais
pas de problèmes :-( Mais je ne peut pas toucher à la base, donc je doit
faire avec.
Note : Je pose ma question ici car vous vous y connaissez en langage SQL,
mais la base est une base MySQL. Donc pas de procédure stocké pour faire des
boucles (enfin je pense) et si un autre forum est exclusivement consacré au
SQL, je suis preneur.


Si vous avez une idée, merci d'avance et même merci beaucoup ;-)

Damran

10 réponses

1 2
Avatar
Jean-Francois Cantin
Salut Damran,
juste pour être sûr que je comprends ton besoin, est-ce que cet exemple
correspond à ton besoin ?

ARTICLE #1
|__ ARTICLE #2
|__ ARTICLE #3
|__ARTICLE #4
|__ ARTICLE #5

Supposons que ton ID_PERE est sur l'article #1, tu veux que tous les
articles ( 1, 2, 3, 4 et 5 ) sortent dans une requête ?
Si c'est le cas, j'utilise une petite procédure ( Stored
Procedure )"d'explosion" que je me suis créée pour faire le travail.

Dis-moi si c'est le besoin que tu as.
J-Francois.



"Damran" a écrit dans le message de
news:3fb10a23$0$27043$
Bonjour
J'ai un petit problème.
Pour représenter des articles présent dans un niveau, j'ai un ID_PERE qui
représente donc où est attaché mon article.
Je voudrais à partir d'un niveau, récupérer tous les articles présent en
dessous de ce niveau et ce, quelques soit le nombre de sous niveau.
J'ai beau chercher, j'ai l'impression que c'est impossible en une seule
requête.
Haa là là, si la base utilisait la représentation intervallaire, je


n'aurais
pas de problèmes :-( Mais je ne peut pas toucher à la base, donc je doit
faire avec.
Note : Je pose ma question ici car vous vous y connaissez en langage SQL,
mais la base est une base MySQL. Donc pas de procédure stocké pour faire


des
boucles (enfin je pense) et si un autre forum est exclusivement consacré


au
SQL, je suis preneur.


Si vous avez une idée, merci d'avance et même merci beaucoup ;-)

Damran




Avatar
Damran
"Jean-Francois Cantin" a écrit dans le
message de news: enjIP#

Salut Damran,


Bonjour

juste pour être sûr que je comprends ton besoin, est-ce que cet exemple
correspond à ton besoin ?

ARTICLE #1
|__ ARTICLE #2
|__ ARTICLE #3
|__ARTICLE #4
|__ ARTICLE #5

Supposons que ton ID_PERE est sur l'article #1, tu veux que tous les
articles ( 1, 2, 3, 4 et 5 ) sortent dans une requête ?
Si c'est le cas, j'utilise une petite procédure ( Stored
Procedure )"d'explosion" que je me suis créée pour faire le travail.

Dis-moi si c'est le besoin que tu as.


Oui c'est ça, sauf que je ne n'ai besoin que des "feuilles" de mon arbre.


Merci
Damran
Avatar
Jean-Francois Cantin
Okay.
L'idée, c'est de créer une table temporaire dans laquelle tu insère toutes
tes données

Prenons par exemple mon arbre de tantot, schématisé ainsi :

ID_PERE ID_ENFANT VALEUR
1 1 ARTICLE #1
1 2 ARTICLE #2
1 3 ARTICLE #3
3 4 ARTICLE #4
4 5 ARTICLE #5

CREATE TABLE #EXPLOSE (ID_PERE INT, ID_ENFANT INT, VALEUR VARCHAR(50),
NIVEAU INT)
SET @NIVEAU = 0
INSERT INTO #EXPLOSE
SELECT ID_PERE, ID_ENFANT, VALEUR, @NIVEAU FROM MATABLE WHERE ID_PERE ID_ENFANT

WHILE @@ROWCOUNT <> 0
BEGIN
SET @NIVEAU = @NIVEAU + 1
INSERT INTO #EXPLOSE
SELECT ID_PERE, ID_ENFANT, VALEUR, @NIVEAU FROM MATABLE WHERE
ID_PERE <> ID_ENFANT
AND EXISTS ( SELECT * FROM #EXPLOSE WHERE ID_ENFANT MATABLE.ID_PERE AND #EXPLOSE.NIVEAU = @NIVEAU - 1)
END

DELETE FROM #EXPLOSE WHERE NIVEAU = 0



Ce code devrait te sortir la liste de tes feuilles.
Bonne chance :p
J-François





"Damran" a écrit dans le message de
news:3fb219b0$0$225$

"Jean-Francois Cantin" a écrit dans le
message de news: enjIP#
>
> Salut Damran,
Bonjour

> juste pour être sûr que je comprends ton besoin, est-ce que cet exemple
> correspond à ton besoin ?
>
> ARTICLE #1
> |__ ARTICLE #2
> |__ ARTICLE #3
> |__ARTICLE #4
> |__ ARTICLE #5
>
> Supposons que ton ID_PERE est sur l'article #1, tu veux que tous les
> articles ( 1, 2, 3, 4 et 5 ) sortent dans une requête ?
> Si c'est le cas, j'utilise une petite procédure ( Stored
> Procedure )"d'explosion" que je me suis créée pour faire le travail.
>
> Dis-moi si c'est le besoin que tu as.
Oui c'est ça, sauf que je ne n'ai besoin que des "feuilles" de mon arbre.


Merci
Damran




Avatar
Fred BROUARD
Effectivement il n'est pas possible de faire cela en une seule requête,
même en y incluant des sous requêtes.

EN revanche, lorsque SQL Server aura implémenté le niveau SQL:1999 il
sera sans doute possible de faire des requêtes récursives de ce genre :
WITH RECURSIVE trajet (depart, arrivee)
AS (SELECT VLS_DEPART, VLS_ARRIVEE
FROM T_VOLS_VLS
UNION ALL
SELECT debut.depart, suite.VLS_ARRIVEE
FROM trajet debut
INNER JOIN T_VOLS_VLS suite
ON debut.arrive = suite.VLS_DEPART)
SELECT *
FROM trajet
WHERE depart = 'NICE'
AND arrivee = 'BORDEAUX'

Mais en attendant il y a deux solutions... L'une t'as déjà été donnée,
elle est peu efficace. elle consiste à créer des procédures stockées
très couteuses en verouillage et temps d'exécution.

L'autre est infiniment plus simple : elle consiste à modéliser ton arbre
par intervalle et dès lors, toutes tes requêtes ne se feront plus que
par de simples SELECT sans aucune sous requêtes complexes.

A lire sur le sujet :
http://sqlpro.developpez.com/Tree/SQL_tree.html
(Avec le code pour SQL Server...)

--
Frédéric BROUARD - expert SQL, spécialiste : SQL Server / Delphi / web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
****************** mailto: ******************

Damran a écrit:
Bonjour
J'ai un petit problème.
Pour représenter des articles présent dans un niveau, j'ai un ID_PERE qui
représente donc où est attaché mon article.
Je voudrais à partir d'un niveau, récupérer tous les articles présent en
dessous de ce niveau et ce, quelques soit le nombre de sous niveau.
J'ai beau chercher, j'ai l'impression que c'est impossible en une seule
requête.
Haa là là, si la base utilisait la représentation intervallaire, je n'aurais
pas de problèmes :-( Mais je ne peut pas toucher à la base, donc je doit
faire avec.
Note : Je pose ma question ici car vous vous y connaissez en langage SQL,
mais la base est une base MySQL. Donc pas de procédure stocké pour faire des
boucles (enfin je pense) et si un autre forum est exclusivement consacré au
SQL, je suis preneur.


Si vous avez une idée, merci d'avance et même merci beaucoup ;-)

Damran




Avatar
Jean-Francois Cantin
Fred,
qu'est-ce qu'une modélisation par intervalle ?


"Fred BROUARD" a écrit dans le message de
news:
Effectivement il n'est pas possible de faire cela en une seule requête,
même en y incluant des sous requêtes.

EN revanche, lorsque SQL Server aura implémenté le niveau SQL:1999 il
sera sans doute possible de faire des requêtes récursives de ce genre :
WITH RECURSIVE trajet (depart, arrivee)
AS (SELECT VLS_DEPART, VLS_ARRIVEE
FROM T_VOLS_VLS
UNION ALL
SELECT debut.depart, suite.VLS_ARRIVEE
FROM trajet debut
INNER JOIN T_VOLS_VLS suite
ON debut.arrive = suite.VLS_DEPART)
SELECT *
FROM trajet
WHERE depart = 'NICE'
AND arrivee = 'BORDEAUX'

Mais en attendant il y a deux solutions... L'une t'as déjà été donnée,
elle est peu efficace. elle consiste à créer des procédures stockées
très couteuses en verouillage et temps d'exécution.

L'autre est infiniment plus simple : elle consiste à modéliser ton arbre
par intervalle et dès lors, toutes tes requêtes ne se feront plus que
par de simples SELECT sans aucune sous requêtes complexes.

A lire sur le sujet :
http://sqlpro.developpez.com/Tree/SQL_tree.html
(Avec le code pour SQL Server...)

--
Frédéric BROUARD - expert SQL, spécialiste : SQL Server / Delphi / web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
****************** mailto: ******************

Damran a écrit:
> Bonjour
> J'ai un petit problème.
> Pour représenter des articles présent dans un niveau, j'ai un ID_PERE


qui
> représente donc où est attaché mon article.
> Je voudrais à partir d'un niveau, récupérer tous les articles présent en
> dessous de ce niveau et ce, quelques soit le nombre de sous niveau.
> J'ai beau chercher, j'ai l'impression que c'est impossible en une seule
> requête.
> Haa là là, si la base utilisait la représentation intervallaire, je


n'aurais
> pas de problèmes :-( Mais je ne peut pas toucher à la base, donc je doit
> faire avec.
> Note : Je pose ma question ici car vous vous y connaissez en langage


SQL,
> mais la base est une base MySQL. Donc pas de procédure stocké pour faire


des
> boucles (enfin je pense) et si un autre forum est exclusivement consacré


au
> SQL, je suis preneur.
>
>
> Si vous avez une idée, merci d'avance et même merci beaucoup ;-)
>
> Damran
>
>



Avatar
Damran
"Jean-Francois Cantin" a écrit dans le
message de news: e0z8$
Fred,
qu'est-ce qu'une modélisation par intervalle ?


C'est une technique qui permet de gérer un arbre via des bornes (borne
gauche et droite).
Suivant la valeur des bornes, on peut sortir en un seul select n'importe
quel type de question que l'on peut avoir sur un arbre.
Voici un lien très instructif :
http://sqlpro.developpez.com/Tree/SQL_tree.html (déjà donnée par Fred)
C'est un peu lourd pour l'insertion, mais pour le select, c'est le top.


Damran
Avatar
Jean-Francois Cantin
Nous utilisons ici une modélisation parent-enfant pour la gestion de nos
assemblages de produit.
Par exemple, prenons le produit A

A
|__ B
| |__ C
| |__ D
|___E
|__F

Ma structure de table ressemble à ceci :

ProduitParent ProduitEnfant
A A
A B
A E
B C
B D
E F

Jusqu'ici, je ne vois pas trpo de complication pour gérer cet arbre en
intervalle.

ProduitParent ProduitEnfant BorneGauche BorneDroite
A A 1 12
A B 2 7
A E 8
11
B C 3 4
B D 5 6
E F 9
10

Cependant, lorsque j'ai un autre produit, le produit Z par exemple, avec
toutes ses sous-composantes, comment est-ce que j'incrémente mes intervalles
? Je ne peux pas toujours procéder par 1,2,3,..., puisque la requête pour
trouver les sous-composants du produit A pourrait sortir ceux du produit Z.

Z
|__ P
| |__ C
| |__ D
|___R
|__F


ProduitParent ProduitEnfant BorneGauche BorneDroite
A A 1 12
A B 2 7
A E 8
11
B C 3 4
B D 5 6
E F 9
10
Z Z 1 12

Z P 2 7
Z R 8
11
P C 3 4
P D 5 6
R F 9
10

De plus, supposons que j'aie créé l'arborescence du produit Z après celle du
A, je pourrais continuer à numéroter les bornes du Z a partir du maximum
déjà attribué pour A, mais lorsque j'irai rajouter un sous-composant au
produit A, je me retrouve avec le même problème : il y a des nombres
utilisés dans Z qui sont entre les nombres utilisés dans les bornes de A.

Comment procéder ?

Merci.



"Damran" a écrit dans le message de
news:3fb23ba5$0$228$

"Jean-Francois Cantin" a écrit dans le
message de news: e0z8$
> Fred,
> qu'est-ce qu'une modélisation par intervalle ?
C'est une technique qui permet de gérer un arbre via des bornes (borne
gauche et droite).
Suivant la valeur des bornes, on peut sortir en un seul select n'importe
quel type de question que l'on peut avoir sur un arbre.
Voici un lien très instructif :
http://sqlpro.developpez.com/Tree/SQL_tree.html (déjà donnée par Fred)
C'est un peu lourd pour l'insertion, mais pour le select, c'est le top.


Damran




Avatar
Damran
"Jean-Francois Cantin" a écrit dans le
message de news:
Nous utilisons ici une modélisation parent-enfant pour la gestion de nos
assemblages de produit.
Par exemple, prenons le produit A

A
|__ B
| |__ C
| |__ D
|___E
|__F

Ma structure de table ressemble à ceci :

ProduitParent ProduitEnfant
A A
A B
A E
B C
B D
E F

Jusqu'ici, je ne vois pas trpo de complication pour gérer cet arbre en
intervalle.

ProduitParent ProduitEnfant BorneGauche BorneDroite
A A 1


12
A B 2


7
A E 8
11
B C 3


4
B D 5


6
E F 9
10

Cependant, lorsque j'ai un autre produit, le produit Z par exemple, avec
toutes ses sous-composantes, comment est-ce que j'incrémente mes


intervalles
? Je ne peux pas toujours procéder par 1,2,3,..., puisque la requête pour
trouver les sous-composants du produit A pourrait sortir ceux du produit


Z.

Z
|__ P
| |__ C
| |__ D
|___R
|__F


ProduitParent ProduitEnfant BorneGauche BorneDroite
A A 1


12
A B 2


7
A E 8
11
B C 3


4
B D 5


6
E F 9
10
Z Z 1


12

Z P 2


7
Z R 8
11
P C 3


4
P D 5


6
R F 9
10

De plus, supposons que j'aie créé l'arborescence du produit Z après celle


du
A, je pourrais continuer à numéroter les bornes du Z a partir du maximum
déjà attribué pour A, mais lorsque j'irai rajouter un sous-composant au
produit A, je me retrouve avec le même problème : il y a des nombres
utilisés dans Z qui sont entre les nombres utilisés dans les bornes de A.

Comment procéder ?


Les bornes doivent être unique. On ne doit pas avoir un même nombre utilisé
pour plusieurs bornes. Si c'est le cas, c'est que l'insertion à été mal
faite.
L'insertion avec cette technique doit se faire en trois étapes car il faut
en fait d'abord décaler toutes les bornes (de 2 pour l'insertion d'une
feuille), pour pouvoir ensuite insérer la nouvelle feuille.
Supposons que l'on veuille insérer un élément Z, fils de B : bornes droite
de B = 7
1/ Mettre à jour toutes les bornes de droites des éléments à décaler (à
droite de l'insertion).
UPDATE TABLE
SET BD = BD + 2
WHERE BD >= 7

2/ Idem pour les bornes gauches des ces élements
UPDATE TABLE
SET BG = BG + 2
WHERE BG >= 7

3/ Insertion de la feuille.
INSERT INTO TABLE(BG, BD, NOM)
VALUES (7, 8, 'Z')

Je (re)donne ce lien :
http://sqlpro.developpez.com/Tree/SQL_tree.html
Tout ceci y est clairement expliqué : Select, Insert etc...


Damran
Avatar
Damran
"Damran" a écrit dans le message de news:
3fb10a23$0$27043$
Bonjour
J'ai un petit problème.
Pour représenter des articles présent dans un niveau, j'ai un ID_PERE qui
représente donc où est attaché mon article.
Je voudrais à partir d'un niveau, récupérer tous les articles présent en
dessous de ce niveau et ce, quelques soit le nombre de sous niveau.
J'ai beau chercher, j'ai l'impression que c'est impossible en une seule
requête.
Haa là là, si la base utilisait la représentation intervallaire, je


n'aurais
pas de problèmes :-( Mais je ne peut pas toucher à la base, donc je doit
faire avec.
Note : Je pose ma question ici car vous vous y connaissez en langage SQL,
mais la base est une base MySQL. Donc pas de procédure stocké pour faire


des
boucles (enfin je pense) et si un autre forum est exclusivement consacré


au
SQL, je suis preneur.


Si vous avez une idée, merci d'avance et même merci beaucoup ;-)


Bonjour
Voici la solution si une base de donnée gère la récursivité :
----
Procedure RecherchePeres (in id integer, inout reponse string)
begin
reponse = reponse + ', ' + (SELECT FAM_LIB
FROM FAMILLE
WHERE FAM_ID = ID)
if id = 0
then
return
else
id = (SELECT FAM_PERE
FROM FAMILLE
WHERE FAM_ID = ID)
end
----
Il faudrait en fait que je transforme cette procédure en code (php ou asp)
utilisant des recordset.
J'ai posté ici car vous connaissez bien le SQL, mais le problème dont je
parles tournes sous MySQL/php, donc pas de procédures stocké.

Et je ne vois pas trop comment fonctionne les "boucles" dans cette
procédure.

Vous avez une idée pour faire cela en php, ou asp (je porterai le code s'il
le faut) ? Je suppose que je doit avoir une fonction qui fait un select sur
l'ID, puis je devrais appeler cette fonction à partir d'elle même pour avoir
la récursivité. J'ai jamais fait de fonction récursive et je n'arrive pas
encore à m'imaginer comment se déroule ce genre d'algo.

Si vous pouviez me mettre sur la voie.


Damran
Avatar
Damran
"Damran" a écrit dans le message de news:
3fb32f6b$0$10423$
Bonjour
Voici la solution si une base de donnée gère la récursivité :
----
Procedure RecherchePeres (in id integer, inout reponse string)
begin
reponse = reponse + ', ' + (SELECT FAM_LIB
FROM FAMILLE
WHERE FAM_ID = ID)
if id = 0
then
return
else
id = (SELECT FAM_PERE
FROM FAMILLE
WHERE FAM_ID = ID)
end
----
Il faudrait en fait que je transforme cette procédure en code (php ou asp)
utilisant des recordset.
J'ai posté ici car vous connaissez bien le SQL, mais le problème dont je
parles tournes sous MySQL/php, donc pas de procédures stocké.

Et je ne vois pas trop comment fonctionne les "boucles" dans cette
procédure.

Vous avez une idée pour faire cela en php, ou asp (je porterai le code


s'il
le faut) ? Je suppose que je doit avoir une fonction qui fait un select


sur
l'ID, puis je devrais appeler cette fonction à partir d'elle même pour


avoir
la récursivité. J'ai jamais fait de fonction récursive et je n'arrive pas
encore à m'imaginer comment se déroule ce genre d'algo.

Si vous pouviez me mettre sur la voie.




J'ai oublié de préciser.
Le but serait de trouver tous les FAM_PERE concernés pour ensuite construire
une condition à utiliser dans une autre requête : "Where FAM_PERE = 1 or
FAM_PERE = 2 ...

Damran
1 2