Afficher les liaisons des liaisons

8 réponses
Avatar
Y a personne
Soit 2 tables

tbl_fiches
id
titre

tbl_liaisons
id
fk_fiche1
fk_fiche2


Je lie la fiche 1 au fiches 2, 3 et 12 (ligne 1, 2 et 6)
je lie la fiche 3 à la 4 (ligne 3)
je lie la fiche 4 à la 5 (ligne 4)
...

J'ai donc ceci ds la table tbl_liaisons :
1 1 2
2 1 3
3 4 3
4 4 5
5 6 9
6 12 1
7 5 17
...

Si j'affiche la fiche 3, je voudrais afficher toutes les fiches liés.
Donc, les fiches 1 et 4 mais aussi les liaisons de celles-ci et ainsi de
suite 2, 12, 5 et 17

Et là, je coince, j'ai un peu de mal à trouver tous les niveaux.

merci de votre aide

8 réponses

Avatar
Ph. B.
Y a personne a écrit :
Soit 2 tables

tbl_fiches
id
titre

tbl_liaisons
id
fk_fiche1
fk_fiche2


Je lie la fiche 1 au fiches 2, 3 et 12 (ligne 1, 2 et 6)
je lie la fiche 3 à la 4 (ligne 3)
je lie la fiche 4 à la 5 (ligne 4)
...

J'ai donc ceci ds la table tbl_liaisons :
1 1 2
2 1 3
3 4 3
4 4 5
5 6 9
6 12 1
7 5 17
...

Si j'affiche la fiche 3, je voudrais afficher toutes les fiches liés.
Donc, les fiches 1 et 4 mais aussi les liaisons de celles-ci et ainsi de
suite 2, 12, 5 et 17

Et là, je coince, j'ai un peu de mal à trouver tous les niveaux.

merci de votre aide



Quelle requête avez vous écrit pour y parvenir ?
Avatar
Y a personne
Le 13/09/2011 08:13, Ph. B. a écrit :
Y a personne a écrit :
Soit 2 tables

tbl_fiches
id
titre

tbl_liaisons
id
fk_fiche1
fk_fiche2


Je lie la fiche 1 au fiches 2, 3 et 12 (ligne 1, 2 et 6)
je lie la fiche 3 à la 4 (ligne 3)
je lie la fiche 4 à la 5 (ligne 4)
...

J'ai donc ceci ds la table tbl_liaisons :
1 1 2
2 1 3
3 4 3
4 4 5
5 6 9
6 12 1
7 5 17
...

Si j'affiche la fiche 3, je voudrais afficher toutes les fiches liés.
Donc, les fiches 1 et 4 mais aussi les liaisons de celles-ci et ainsi de
suite 2, 12, 5 et 17

Et là, je coince, j'ai un peu de mal à trouver tous les niveaux.

merci de votre aide



Quelle requête avez vous écrit pour y parvenir ?




Avec cette méthode, je n'ai que le premier niveau.
Je dois sans doute continuer a refaire les recherches mais cela risque
d'être long et lourd.

Y'a t'il une meilleurs structure pour ce genre de liaisons ?


function affiche_liaisons($id)
{
$Liaisons = array();
$txt="";

$sql="
SELECT fk_fiche1, fk_fiche2 FROM tbl_liaisons
WHERE fk_fiche1='".$id."' OR fk_fiche2='".$id."'
";

$req=_exec_sql($sql);

while ($data=mysql_fetch_array($req))
{
$fk_fiche1 = $data['fk_fiche1'];
$fk_fiche2 = $data['fk_fiche2'];

$fk_fiche = $fk_fiche1;
if ($fk_fiche1==$id)
$fk_fiche = $fk_fiche2;

if (!in_array($fk_fiche, $Liaisons))
$Liaisons[] = $fk_fiche;
}


if (count($Liaisons)>0)
{
$sql="
SELECT fk_fiche1, fk_fiche2 FROM tbl_liaisons
WHERE
";

for ($i=0, $T=count($Liaisons); $i<$T; $i++)
{
if ($i>0)
$sql.=" OR ";

$sql.=" fk_fiche1='".$Liaisons[$i]."' OR fk_fiche2='".$Liaisons[$i]."'";
}

$req=_exec_sql($sql);

while ($data=mysql_fetch_array($req))
{
$fk_fiche1 = $data['fk_fiche1'];
$fk_fiche2 = $data['fk_fiche2'];

if ($fk_fiche1!=$id and !in_array($fk_fiche1, $Liaisons))
$Liaisons[] = $fk_fiche1;

if ($fk_fiche2!=$id and !in_array($fk_fiche2, $Liaisons))
$Liaisons[] = $fk_fiche2;
}
}

//Ici j'affiche les fiches
if (count($Liaisons)>0)
{
$sql="
SELECT titre FROM ".TABLE."
WHERE
";

for ($i=0, $T=count($Liaisons); $i<$T; $i++)
{
if ($i>0)
$sql.=" OR ";

$sql.=" id='".$Liaisons[$i]."' ";
}

$req=_exec_sql($sql);

while ($data=mysql_fetch_array($req))
{
$titre = $data['titre'];

$txt.= "-".$titre."<br />";
}
}

return $txt;
}


merci
Avatar
Ph. B.
Y a personne a écrit :
Le 13/09/2011 08:13, Ph. B. a écrit :
Y a personne a écrit :
Soit 2 tables

tbl_fiches
id
titre

tbl_liaisons
id
fk_fiche1
fk_fiche2


Je lie la fiche 1 au fiches 2, 3 et 12 (ligne 1, 2 et 6)
je lie la fiche 3 à la 4 (ligne 3)
je lie la fiche 4 à la 5 (ligne 4)
...

J'ai donc ceci ds la table tbl_liaisons :
1 1 2
2 1 3
3 4 3
4 4 5
5 6 9
6 12 1
7 5 17
...

Si j'affiche la fiche 3, je voudrais afficher toutes les fiches liés.
Donc, les fiches 1 et 4 mais aussi les liaisons de celles-ci et ainsi de
suite 2, 12, 5 et 17

Et là, je coince, j'ai un peu de mal à trouver tous les niveaux.

merci de votre aide



Quelle requête avez vous écrit pour y parvenir ?




Avec cette méthode, je n'ai que le premier niveau.
Je dois sans doute continuer a refaire les recherches mais cela risque
d'être long et lourd.

Y'a t'il une meilleurs structure pour ce genre de liaisons ?



Effectivement, il faut faire cela de manière récursive et cela peut être
long et lourd.
On peut utiliser les requêtes récursives (si ton SGBD les comprend) ou
une procédure stockée récursive.

Auparavant, j'ai une question sur ton modèle de données.

1°) La table liaison ne me parait pas commutative. Dans ton exemple, on a :

Id Fiche Fiche liée
1 1 2
2 1 3
6 12 1

L'ordre du lien semble important. L'est-il ? Sinon on aurait
Id Fiche Fiche liée
1 1 2
2 1 3
6 1 12

2°) la réponse passe par une requête récursive (traiter cela par
programmation est AMHA aberrant).

Si la réponse à ma 1° question est que l'ordre du lien n'est pas
important, c.a.d. que pour tout lien l'Id le plus petit sera à gauche,
une requête récursive suffit.

Dans ce cas, prenons le jeu d'essais pour la table tbl_liaisons :
-----------------------------------------------------------------
1 1 2
2 1 3
3 3 4
4 4 5
5 6 9
6 1 12
7 5 17
Le résultat attendu sera :
--------------------------
Fiche Fiche liée
1 2
1 3
1 4
1 5
1 12
1 17
3 4
3 5
3 17
4 5
4 17
5 17
6 9
La requête permettant de l'obtenir :
------------------------------------
with recursive fiches_liees(fiche, fiche_liee) as
(
select fk_fiche1, fk_fiche2 from tbl_liaisons
union all
select fl.fiche, li.fk_fiche2 from tbl_liaisons as li
inner join fiches_liees as fl on li.fk_fiche1 = fl.fiche_liee
)
select distinct fiche, fiche_liee from fiches_liees

Dans le cas contraire, c'est à dire que l'ordre du lien entre fiches est
important (1 liée à 2 n'est pas équivalent à 2 liée à 1) et que tu veux
tous les liens il faut complexifier la requête...
--
Philippe.
Avatar
Denis Beauregard
Le Tue, 13 Sep 2011 01:33:16 +0200, Y a personne
écrivait dans fr.comp.applications.sgbd:

Soit 2 tables

tbl_fiches
id
titre

J'ai donc ceci ds la table tbl_liaisons :
1 1 2
2 1 3
3 4 3
4 4 5
5 6 9
6 12 1
7 5 17
...

Si j'affiche la fiche 3, je voudrais afficher toutes les fiches liés.
Donc, les fiches 1 et 4 mais aussi les liaisons de celles-ci et ainsi de
suite 2, 12, 5 et 17

Et là, je coince, j'ai un peu de mal à trouver tous les niveaux.



Petite question : est-ce que la table des liens est très grande ? Et
aussi, est-ce que toutes les liaisons sont utilisées ?

Ce qui est lent, c'est d'aller chercher les données dans la BD,
surtout si on doit faire beaucoup de requêtes.

Alors, pourquoi ne pas lire les liaisons au complet, dans un tableau,
et ensuite utiliser directement ce tableau ? Évidemment, si on a
100 000 liaisons et qu'on en utilise 10 à la fois, cette solution
n'est pas utilisable !


Denis
Avatar
Y a personne
Le 13/09/2011 15:08, Ph. B. a écrit :
Y a personne a écrit :
Le 13/09/2011 08:13, Ph. B. a écrit :
Y a personne a écrit :
Soit 2 tables

tbl_fiches
id
titre

tbl_liaisons
id
fk_fiche1
fk_fiche2


Je lie la fiche 1 au fiches 2, 3 et 12 (ligne 1, 2 et 6)
je lie la fiche 3 à la 4 (ligne 3)
je lie la fiche 4 à la 5 (ligne 4)
...

J'ai donc ceci ds la table tbl_liaisons :
1 1 2
2 1 3
3 4 3
4 4 5
5 6 9
6 12 1
7 5 17
...

Si j'affiche la fiche 3, je voudrais afficher toutes les fiches liés.
Donc, les fiches 1 et 4 mais aussi les liaisons de celles-ci et
ainsi de
suite 2, 12, 5 et 17

Et là, je coince, j'ai un peu de mal à trouver tous les niveaux.

merci de votre aide



Quelle requête avez vous écrit pour y parvenir ?




Avec cette méthode, je n'ai que le premier niveau.
Je dois sans doute continuer a refaire les recherches mais cela risque
d'être long et lourd.

Y'a t'il une meilleurs structure pour ce genre de liaisons ?



Effectivement, il faut faire cela de manière récursive et cela peut être
long et lourd.
On peut utiliser les requêtes récursives (si ton SGBD les comprend) ou
une procédure stockée récursive.

Auparavant, j'ai une question sur ton modèle de données.

1°) La table liaison ne me parait pas commutative. Dans ton exemple, on a :

Id Fiche Fiche liée
1 1 2
2 1 3
6 12 1

L'ordre du lien semble important. L'est-il ? Sinon on aurait
Id Fiche Fiche liée
1 1 2
2 1 3
6 1 12

2°) la réponse passe par une requête récursive (traiter cela par
programmation est AMHA aberrant).

Si la réponse à ma 1° question est que l'ordre du lien n'est pas
important, c.a.d. que pour tout lien l'Id le plus petit sera à gauche,
une requête récursive suffit.

Dans ce cas, prenons le jeu d'essais pour la table tbl_liaisons :
-----------------------------------------------------------------
1 1 2
2 1 3
3 3 4
4 4 5
5 6 9
6 1 12
7 5 17
Le résultat attendu sera :
--------------------------
Fiche Fiche liée
1 2
1 3
1 4
1 5
1 12
1 17
3 4
3 5
3 17
4 5
4 17
5 17
6 9
La requête permettant de l'obtenir :
------------------------------------
with recursive fiches_liees(fiche, fiche_liee) as
(
select fk_fiche1, fk_fiche2 from tbl_liaisons
union all
select fl.fiche, li.fk_fiche2 from tbl_liaisons as li
inner join fiches_liees as fl on li.fk_fiche1 = fl.fiche_liee
)
select distinct fiche, fiche_liee from fiches_liees

Dans le cas contraire, c'est à dire que l'ordre du lien entre fiches est
important (1 liée à 2 n'est pas équivalent à 2 liée à 1) et que tu veux
tous les liens il faut complexifier la requête...




Merci

je n'ai pas trop compris ta requête mais vais analyser ca dès que j'ai
un peu de temps.

Si par exemple la fiche 1 est lié à la 3,
y'a aucune importance que ce soit 1 3 ou 3 1.
Le but de ces liaisons est de trouver toutes les fiches liées
directement et indirectement.
Avatar
Y a personne
Le 13/09/2011 15:37, Denis Beauregard a écrit :
Le Tue, 13 Sep 2011 01:33:16 +0200, Y a personne
écrivait dans fr.comp.applications.sgbd:

Soit 2 tables

tbl_fiches
id
titre

J'ai donc ceci ds la table tbl_liaisons :
1 1 2
2 1 3
3 4 3
4 4 5
5 6 9
6 12 1
7 5 17
...

Si j'affiche la fiche 3, je voudrais afficher toutes les fiches liés.
Donc, les fiches 1 et 4 mais aussi les liaisons de celles-ci et ainsi de
suite 2, 12, 5 et 17

Et là, je coince, j'ai un peu de mal à trouver tous les niveaux.



Petite question : est-ce que la table des liens est très grande ? Et
aussi, est-ce que toutes les liaisons sont utilisées ?

Ce qui est lent, c'est d'aller chercher les données dans la BD,
surtout si on doit faire beaucoup de requêtes.

Alors, pourquoi ne pas lire les liaisons au complet, dans un tableau,
et ensuite utiliser directement ce tableau ? Évidemment, si on a
100 000 liaisons et qu'on en utilise 10 à la fois, cette solution
n'est pas utilisable !


Denis





Bonsoir,

La table (tbl_liaisons) pour le moment n'est pas très grande, je fais
des tests (je peux d'ailleurs changer la logique si je ne trouve pas de
solution).

Je voulais savoir si y'avait une solution pour ce genre de cas.

Je suis entrain de penser à un algorithme avec 2 arrays, je dois y
réfléchir dès que j'ai le temps

merci
Avatar
Ph. B.
Y a personne a écrit :
...
with recursive fiches_liees(fiche, fiche_liee) as
(
select fk_fiche1, fk_fiche2 from tbl_liaisons
union all
select fl.fiche, li.fk_fiche2 from tbl_liaisons as li
inner join fiches_liees as fl on li.fk_fiche1 = fl.fiche_liee
)
select distinct fiche, fiche_liee from fiches_liees

Dans le cas contraire, c'est à dire que l'ordre du lien entre fiches est
important (1 liée à 2 n'est pas équivalent à 2 liée à 1) et que tu veux
tous les liens il faut complexifier la requête...




Merci

je n'ai pas trop compris ta requête mais vais analyser ca dès que j'ai
un peu de temps.



Requête récursive (j'espère que ton SGBD l'accepte):
Le 1° "select" représente le cas limite de la récursion.
Le 2° "select" est la partie récursive qui reboucle grâce au CTE.

Si par exemple la fiche 1 est lié à la 3,
y'a aucune importance que ce soit 1 3 ou 3 1.
Le but de ces liaisons est de trouver toutes les fiches liées
directement et indirectement.



Dans ce cas, il faudrait enregistrer les couples de liaison en plaçant
en 1° l'id de fiche le + faible ; on aurait (Id, fk_fiche1, fk_fiche2) =
(i, n, m) avec n < m quelque soit i. La requête que je t'ai donnée
serait opérationnelle telle que...

Elle peut aussi être ajuster pour pr exemple ramener que les fiches
liées à la fiche 1. Il suffirait d'écrire :
with recursive fiches_liees(fiche, fiche_liee) as
(
select fk_fiche1, fk_fiche2 from tbl_liaisons
union all
select fl.fiche, li.fk_fiche2 from tbl_liaisons as li
inner join fiches_liees as fl on li.fk_fiche1 = fl.fiche_liee
)
select distinct fiche, fiche_liee from fiches_liees
where fiche = 1

--
Philippe.
Avatar
Y a personne
Le 13/09/2011 22:02, Ph. B. a écrit :
Y a personne a écrit :
...
with recursive fiches_liees(fiche, fiche_liee) as
(
select fk_fiche1, fk_fiche2 from tbl_liaisons
union all
select fl.fiche, li.fk_fiche2 from tbl_liaisons as li
inner join fiches_liees as fl on li.fk_fiche1 = fl.fiche_liee
)
select distinct fiche, fiche_liee from fiches_liees

Dans le cas contraire, c'est à dire que l'ordre du lien entre fiches est
important (1 liée à 2 n'est pas équivalent à 2 liée à 1) et que tu veux
tous les liens il faut complexifier la requête...




Merci

je n'ai pas trop compris ta requête mais vais analyser ca dès que j'ai
un peu de temps.



Requête récursive (j'espère que ton SGBD l'accepte):
Le 1° "select" représente le cas limite de la récursion.
Le 2° "select" est la partie récursive qui reboucle grâce au CTE.

Si par exemple la fiche 1 est lié à la 3,
y'a aucune importance que ce soit 1 3 ou 3 1.
Le but de ces liaisons est de trouver toutes les fiches liées
directement et indirectement.



Dans ce cas, il faudrait enregistrer les couples de liaison en plaçant
en 1° l'id de fiche le + faible ; on aurait (Id, fk_fiche1, fk_fiche2) > (i, n, m) avec n < m quelque soit i. La requête que je t'ai donnée
serait opérationnelle telle que...

Elle peut aussi être ajuster pour pr exemple ramener que les fiches
liées à la fiche 1. Il suffirait d'écrire :
with recursive fiches_liees(fiche, fiche_liee) as
(
select fk_fiche1, fk_fiche2 from tbl_liaisons
union all
select fl.fiche, li.fk_fiche2 from tbl_liaisons as li
inner join fiches_liees as fl on li.fk_fiche1 = fl.fiche_liee
)
select distinct fiche, fiche_liee from fiches_liees
where fiche = 1





Voilà

après quelques tests, je suis arrivé (je pense) à une solution :

j'utilise 2 arrays comme j'y avais pensé au début

Je vais quand même garder ton code de coté et l’analyser plus tard, merci


/*
Le but est de mettre dans $Liaisons toutes les fiches qui sont liées
directement à la fiche ID.
Avec ma solution, ID ce trouve en première position ds $Liaisons

ex :
la fiche 8 est lié à 4, 11 et 20
20 est lié à 12
11 est lié à 99
99 est lié à 77

La liaisons fk_fiche1 ou fk_fiche2 n'a pas d'importance.

Après la fonction, $Liaisons contiendra toutes les liaisons


tbl_liaisons
(lia_id, lia_fk_fiche1, lia_fk_fiche2)

1 8 4
2 8 11
3 20 8
4 12 20
5 11 99
6 77 99
*/

$Liaisons = array();
$Liaisons2 = array();

$Liaisons[] = ID;

while ($Liaisons != $Liaisons2)
{
$Liaisons2 = $Liaisons;

for ($i=0, $T=count($Liaisons); $i<$T; $i++)
{
$sql="
SELECT lia_fk_fiche1, lia_fk_fiche2
FROM tbl_liaisons
WHERE
lia_fk_fiche1='".$Liaisons[$i]."' OR
lia_fk_fiche2='".$Liaisons[$i]."'
";

$req=_exec_sql($sql);

while ($data=mysql_fetch_array($req))
{
$fk_fiche1 = $data['lia_fk_fiche1'];
$fk_fiche2 = $data['lia_fk_fiche2'];


if ($fk_fiche1!=ID and
!in_array($fk_fiche1, $Liaisons))
$Liaisons[] = $fk_fiche1;

if ($fk_fiche2!=ID and
!in_array($fk_fiche2, $Liaisons))
$Liaisons[] = $fk_fiche2;
}
}
}