GNT sans publicité, site mobile, fonctionnalitées exclusives...

conception base avec relation deux à plusieurs

Le
Benoit Izac
Bonjour,

Je bute sur la modélisation de ma base de donnée et j'ai beau tourner le
problème dans tous les sens, je ne vois pas quelle solution adopter.

J'ai une table SITE :
- site_id -> clé primaire
- nom
- longitude
- latitude
- adresse
- etc.

Je souhaite créer des liaisons point à point entre ces sites. J'ai donc
une relation deux à plusieurs : si je crée une table LIEN, un lien
contient exactement 2 sites et un site peut apparaître dans 0 ou
plusieurs liens.

J'ai des informations
- qui sont propres au lien : bande de fréquence utilisée, débit,
etc.
- qui sont dépendantes du lien et du site : hauteur de
l'installation sur le site, type d'antenne, etc.

Jusqu'ici, pas de problème, je crée une table LIEN :
- site_id -> clé primaire
- bande de fréquence
- débit

puis une table intermédiaire SITE_LIEN :
- site_id -+
- lien_id -+-> clé primaire
- hauteur
- antenne

Rajoutons une contrainte : je dois conserver le sens du lien : site de
départ (A), site de départ (B). Je modifie donc ma table SITE_LIEN :
- lien_id -+
- coté (A ou B) -+-> clé primaire
- site_id
- hauteur
- antenne

À ce stade, j'ai déjà quelques questions :
1) comment afficher une ligne avec les informations suivantes ?
- lien_id
- site_id où le coté est A
- site_id où le coté est B
2) comment afficher tous les sites qui appartiennent à un lien comme il
suit ?
- site_id
- site_id du distant

Autre chose : j'ai lu qu'il ne fallait pas stocker des informations que
l'on pouvait calculer. Il se trouve qu'il y des informations que je peux
calculer si je connais une extrémité ; par exemple, l'azimut (angle par
rapport au nord) est égal à celui du site distant + ou - 180°. La
fréquence est dite « haute » si celle d'en face est dite « basse ».

Avec toutes ces contraintes, j'en arrive à me dire qu'il est plus simple
de supprimer la table intermédiaire et d'avoir une table LIEN comme il
suit :
- lien_id
- bande de fréquence
- débit
- id_site_A
- antenne_A
- hauteur_A
- azimut_A
- fréquence_A
- id_site_B
- antenne_B
- hauteur_B

Mais ça me crée d'autre problème. Pour répondre à la question 2), je
dois faire deux requêtes puis une union (non testé) :
CREATE VIEW site_A AS
SELECT id_site_A AS local, id_site_B AS distant FROM LIEN;
CREATE VIEW site_B AS
SELECT id_site_B AS local, id_site_A AS distant FROM LIEN;
SELECT * FROM site_A
UNION
SELECT * FROM site_B;

Bref, mon manque d'expérience m'empêche de savoir quelle solution
adopter. Pouvez-vous m'indiquer d'une part si ces deux solutions sont
viables et d'autres part quels sont leurs avantages/inconvénients ?

Merci.
--
Benoit Izac
Lire les 10 réponses

Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
pif34
Le #23925411
Bonjour, pas évident, les explications sont pas super claires, mais
c'est aussi un peu logique, car sinon, pas de problème pour modéliser...



Le 01/11/2011 09:59, Benoit Izac a écrit :
Bonjour,

Je bute sur la modélisation de ma base de donnée et j'ai beau tourner le
problème dans tous les sens, je ne vois pas quelle solution adopter.

J'ai une table SITE :
- site_id -> clé primaire
- nom
- longitude
- latitude
- adresse
- etc.

Je souhaite créer des liaisons point à point entre ces sites. J'ai donc
une relation deux à plusieurs : si je crée une table LIEN, un lien
contient exactement 2 sites et un site peut apparaître dans 0 ou
plusieurs liens.

J'ai des informations
- qui sont propres au lien : bande de fréquence utilisée, débit,
etc.
- qui sont dépendantes du lien et du site : hauteur de
l'installation sur le site, type d'antenne, etc.

Jusqu'ici, pas de problème, je crée une table LIEN :
- site_id -> clé primaire
- bande de fréquence
- débit

puis une table intermédiaire SITE_LIEN :
- site_id -+
- lien_id -+-> clé primaire
- hauteur
- antenne

Rajoutons une contrainte : je dois conserver le sens du lien : site de
départ (A), site de départ (B). Je modifie donc ma table SITE_LIEN :
- lien_id -+
- coté (A ou B) -+-> clé primaire
- site_id
- hauteur
- antenne




bon, alors je résume, en gros t'as un graphe orienté, ce qui reste une
structure de données des plus élémentaires: des sites (les sommets) et
des liens (les aretes):

donc t'as grossomodo 2 entités:

Site (id, nom, gps_x, gps_y, ... )
Lien (id_src, id_dst, bande_frequence, debit, ...).

L'id du site est la PK, les deux ids de liens sont des FK et constituent
toutes les deux une PK de ta table lien (tu peux créer un identifiant si
tu peux avoir plusieurs connexions entre deux meme site ou pour diverses
raison techniques).

si t'as une info dépendante du site (ex: affaiblissement, tu as
grossomodo deux solutions:

- si les attributs ne sont pas tres nombreux, tu modifie la table lien:
Lien (id_src, id_trg, bande_frequence, debit, affaiblissement_src,
affaiblissement_trg, ...).

, tu créé en effet une entité lien avec une laison many to many genre:

Site (id, nom, gps_x, gps_y, ... )
Lien (id, bande_frequence, debit, ...)
et une table d'association:
Lien_Sites (id_site, id_lien, orientation (src ou cible),
affaiblissemet, etc.).

dans ce cas, tu peux mettre une contrainte d'unicité sur (id_lien,
orientation) pour éviter d'avoir plusieurs sources ou destinations
tu peut avoir une PK (ou unicité) sur (id_site,id_lien)...

À ce stade, j'ai déjà quelques questions :
1) comment afficher une ligne avec les informations suivantes ?
- lien_id
- site_id où le coté est A
- site_id où le coté est B



dans le premier cas le plus simple:

select src.id, l.debit, trg.id
from lien l
join site src on lien.id_src = site.id
join site trg on lien.id_trg = site.id


dans le second cas:
select ....
from lien l
join lien_site ls_src on l.id = ls_src.id_lien
and ls_src.orientation = 1
join site src on ls_src.id_site = src.id
join lien_site ls_trg on l.id = ls_trg.id_lien
and ls_trg.orientation = 0
join site trg on ls_trg.id_site = trg.id


2) comment afficher tous les sites qui appartiennent à un lien comme il
suit ?
- site_id
- site_id du distant



premier cas: select * from site where id in (select id_src from lien
where id lien = ?)
union select * from site where id in (select id_trg from lien....)

deuxieme cas:
select * from site where id in (select * id_site from lien_site where
id_lien = ? )


Autre chose : j'ai lu qu'il ne fallait pas stocker des informations que
l'on pouvait calculer. Il se trouve qu'il y des informations que je peux
calculer si je connais une extrémité ; par exemple, l'azimut (angle par
rapport au nord) est égal à celui du site distant + ou - 180°. La
fréquence est dite « haute » si celle d'en face est dite « basse ».



en général, on parle d'attribut calculé:

par exemple t'as la TVA, le HT et le TTC... stocker les 3 n'a pas de
sens car à partir de 2 tu peux en recalculer un 3°...

par contre, en effet, si tu prend l'état civil d'une personne, t'as sexe
M/F sur un seul champ: tu vas pas dire qu'il faut pas stocker F parce
que tu peux le déduire si t'as pas M....

donc si t'as deux type de fréquence H/B... ben tu créé un champ et tu
met la valeur qui va bien...

si par contre t'as une règle qui dit si bande_de_frequence = ??? alors
c'est bas... et que tu stocke la bande de fréquence, en effet, tu stocke
pas la fréquence basse...

au pire, si t'as des règles lourdes à coder et que tu veux éviter la
redondances, tu peux utiliser des mécanismes de vues par exemple,

Avec toutes ces contraintes, j'en arrive à me dire qu'il est plus simple
de supprimer la table intermédiaire et d'avoir une table LIEN comme il
suit :
- lien_id
- bande de fréquence
- débit
- id_site_A
- antenne_A
- hauteur_A
- azimut_A
- fréquence_A
- id_site_B
- antenne_B
- hauteur_B



oui, dépend de l'évolution de ton logiciel... tu va pas créer une table
et plein de jointure pour 1 attributs... si a terme t'en a 10 la
question se pose... si a terme t'as des connexion multiples aussi...

Bref, mon manque d'expérience m'empêche de savoir quelle solution
adopter. Pouvez-vous m'indiquer d'une part si ces deux solutions sont
viables et d'autres part quels sont leurs avantages/inconvénients ?



en l'état avec aussi peu de champs, les deux solutions sont correctes...
la solution compliquées sera cependant plus évolutive dans le temps...

dans tous les cas, tu peux utiliser des vues (j'ai le terme "requete
nommées") pour simplifier un certain nombre de requetes...

d'ailleurs, si tu base tout sur ces vues (sauf insert/delete/update), tu
pourras plus facilement faire évoluer ton schéma sans trop impacter le
reste de l'application ultérieurement....
Benoit Izac
Le #23925871
Bonjour,

le 01/11/2011 à 11:24, pif a écrit dans le message

Bonjour, pas évident, les explications sont pas super claires, mais
c'est aussi un peu logique, car sinon, pas de problème pour
modéliser...



Effectivement. Je pensais avoir tout de même bien décrit le problème.

bon, alors je résume, en gros t'as un graphe orienté, ce qui reste une
structure de données des plus élémentaires: des sites (les sommets) et
des liens (les aretes):



Peut-être, je ne connais absolument rien en théorie des graphes. Si tu
me dis que c'est indispensable pour résoudre mon problème, je veux bien
y jeter un ½il.

donc t'as grossomodo 2 entités:

Site (id, nom, gps_x, gps_y, ... )
Lien (id_src, id_dst, bande_frequence, debit, ...).

L'id du site est la PK, les deux ids de liens sont des FK et
constituent toutes les deux une PK de ta table lien (tu peux créer un
identifiant si tu peux avoir plusieurs connexions entre deux meme site
ou pour diverses raison techniques).

si t'as une info dépendante du site (ex: affaiblissement, tu as
grossomodo deux solutions:

- si les attributs ne sont pas tres nombreux, tu modifie la table lien:
Lien (id_src, id_trg, bande_frequence, debit, affaiblissement_src,
affaiblissement_trg, ...).

, tu créé en effet une entité lien avec une laison many to many genre:

Site (id, nom, gps_x, gps_y, ... )
Lien (id, bande_frequence, debit, ...)
et une table d'association:
Lien_Sites (id_site, id_lien, orientation (src ou cible),
affaiblissemet, etc.).

dans ce cas, tu peux mettre une contrainte d'unicité sur (id_lien,
orientation) pour éviter d'avoir plusieurs sources ou destinations
tu peut avoir une PK (ou unicité) sur (id_site,id_lien)...



Ok, c'est ce que j'ai décrit.

À ce stade, j'ai déjà quelques questions :
1) comment afficher une ligne avec les informations suivantes ?
- lien_id
- site_id où le coté est A
- site_id où le coté est B



dans le premier cas le plus simple:



[je le rappelle pour plus de clarté
Site (id, nom, gps_x, gps_y, ... )
Lien (id_src, id_dst, bande_frequence, debit, ...).
]
select src.id, l.debit, trg.id
from lien l
join site src on lien.id_src = site.id
join site trg on lien.id_trg = site.id



Pour moi c'est un peu plus simple (tu as supprimé lien_id mais ça ne
change rien) :
SELECT id_src, id_dst FROM lien;

dans le second cas:



[
Site (id, nom, gps_x, gps_y, ... )
Lien (id, bande_frequence, debit, ...)
Lien_Sites (id_site, id_lien, orientation (src ou cible),
affaiblissemet, etc.)
]

select ....
from lien l
join lien_site ls_src on l.id = ls_src.id_lien
and ls_src.orientation = 1
join site src on ls_src.id_site = src.id
join lien_site ls_trg on l.id = ls_trg.id_lien
and ls_trg.orientation = 0
join site trg on ls_trg.id_site = trg.id



Il faut que je teste car j'ai du mal a suivre la requête (sans doute
parce que je n'ai pas l'habitude de lire cette syntaxe).

2) comment afficher tous les sites qui appartiennent à un lien comme il
suit ?
- site_id
- site_id du distant



premier cas: select * from site where id in (select id_src from lien
where id lien = ?)
union select * from site where id in (select id_trg from lien....)



Non, pour moi, ça liste tous les sites, mais pas le distant. Ça
correspond à ce que je faisais à la fin de mon post initial avec des
CREATE VIEW et UNION.

deuxieme cas:
select * from site where id in (select * id_site from lien_site where
id_lien = ? )



Même remarque que précédemment et c'est justement ça mon problème,
lister tous les sites de la table de liaison, c'est facile mais faire la
liaison entre src et dst, je ne sais pas faire.

Autre chose : j'ai lu qu'il ne fallait pas stocker des informations que
l'on pouvait calculer. Il se trouve qu'il y des informations que je peux
calculer si je connais une extrémité ; par exemple, l'azimut (angle par
rapport au nord) est égal à celui du site distant + ou - 180°. La
fréquence est dite « haute » si celle d'en face est dite « basse ».



en général, on parle d'attribut calculé:

par exemple t'as la TVA, le HT et le TTC... stocker les 3 n'a pas de
sens car à partir de 2 tu peux en recalculer un 3°...

par contre, en effet, si tu prend l'état civil d'une personne, t'as
sexe M/F sur un seul champ: tu vas pas dire qu'il faut pas stocker
F parce que tu peux le déduire si t'as pas M....



Non, c'est différent, dans le cas de l'état civil, tu peux avoir soit
M ou F et tu n'as pas de contrainte. Si par contre tu prends un couple
(non homosexuel), c'est différent tu ne peux pas avoir deux M ou deux
F dans le même couple. Je veux éviter d'une part, d'avoir des
incohérences (deux bandes hautes dans le même lien, la somme des azimut
qui n'est pas égal à 360°), d'autre part de consommer de l'espace
lorsque ce n'est pas nécessaire. Je pense que seule la table à plat
(sans la table de liaison) me le permet.

donc si t'as deux type de fréquence H/B... ben tu créé un champ et tu
met la valeur qui va bien...

si par contre t'as une règle qui dit si bande_de_frequence = ??? alors
c'est bas... et que tu stocke la bande de fréquence, en effet, tu
stocke pas la fréquence basse...



Il y a une fréquence basse et une fréquence haute dans la bande de
fréquence.

au pire, si t'as des règles lourdes à coder et que tu veux éviter la
redondances, tu peux utiliser des mécanismes de vues par exemple,

Avec toutes ces contraintes, j'en arrive à me dire qu'il est plus simple
de supprimer la table intermédiaire et d'avoir une table LIEN comme il
suit :
- lien_id
- bande de fréquence
- débit
- id_site_A
- antenne_A
- hauteur_A
- azimut_A
- fréquence_A
- id_site_B
- antenne_B
- hauteur_B



oui, dépend de l'évolution de ton logiciel... tu va pas créer une
table et plein de jointure pour 1 attributs... si a terme t'en a 10 la
question se pose... si a terme t'as des connexion multiples aussi...

Bref, mon manque d'expérience m'empêche de savoir quelle solution
adopter. Pouvez-vous m'indiquer d'une part si ces deux solutions sont
viables et d'autres part quels sont leurs avantages/inconvénients ?



en l'état avec aussi peu de champs, les deux solutions sont correctes...



Il y en a bien plus, c'était juste pour l'exemple.

la solution compliquées sera cependant plus évolutive dans le temps...



C'est ce qui me semble aussi.

dans tous les cas, tu peux utiliser des vues (j'ai le terme "requete
nommées") pour simplifier un certain nombre de requetes...

d'ailleurs, si tu base tout sur ces vues (sauf insert/delete/update),
tu pourras plus facilement faire évoluer ton schéma sans trop impacter
le reste de l'application ultérieurement....



Ok, merci pour la réponse.
--
Benoit Izac
pif34
Le #23926001
Le 01/11/2011 13:56, Benoit Izac a écrit :
Peut-être, je ne connais absolument rien en théorie des graphes. Si tu
me dis que c'est indispensable pour résoudre mon problème, je veux bien
y jeter un ½il.



non, en informatique, on retrouve grossomodo deux structures des données
essentiellement: les espaces multidimensionner et les graphes (réseau de
transport de communication, sociaux, etc ...). T'as pas besoin de
connaitre la théorie des graphes, mais je t'en recommande la lecture,
c'est au programme de la première année d'IUT...

je mentionnais ca c'est c'est un terme on ne peut plus courant dans le
métier...

Pour moi c'est un peu plus simple (tu as supprimé lien_id mais ça ne
change rien) :
SELECT id_src, id_dst FROM lien;



ben la jointure que j'avais indiqué, c'était pour retrouver le nom du
site ou autre....

Il faut que je teste car j'ai du mal a suivre la requête (sans doute
parce que je n'ai pas l'habitude de lire cette syntaxe).



c'est du SQL standard

Non, pour moi, ça liste tous les sites, mais pas le distant. Ça
correspond à ce que je faisais à la fin de mon post initial avec des
CREATE VIEW et UNION.



ben les sites sont toujours distants les un des autres... dans tous les
cas, t'as toutes les billes... ce que tu as a faire c'est de requetes
SQL de base avec des jointures, si t'en a jamais fait, je te recommande
une formation ou te d'intéresser un peu plus à ca avant de te lancer...
de toute façon tu y couperas pas...

Même remarque que précédemment et c'est justement ça mon problème,
lister tous les sites de la table de liaison, c'est facile mais faire la
liaison entre src et dst, je ne sais pas faire.



tu fais 2 jointures, c'est tout...


Non, c'est différent, dans le cas de l'état civil, tu peux avoir soit
M ou F et tu n'as pas de contrainte. Si par contre tu prends un couple
(non homosexuel), c'est différent tu ne peux pas avoir deux M ou deux
F dans le même couple. Je veux éviter d'une part, d'avoir des
incohérences (deux bandes hautes dans le même lien, la somme des azimut
qui n'est pas égal à 360°), d'autre part de consommer de l'espace
lorsque ce n'est pas nécessaire. Je pense que seule la table à plat
(sans la table de liaison) me le permet.



l'espace te pose pas trop de question... une base correcte devrait
largement tenir ce que tu lui demande... je connais pas la volumétrie,
mais j'ai pas peur pour quelques champs vides...

la; je maitrise pas les questions métiers, donc c'est pas la peine
d'aller plus loin.. t'as les éléments de base, je t'ai expliqué ce qu'on
appelle champ calculé... c'est un attribut qui peut etre calculé à
partir des autres. A toi de voir si tu peux le faire ou pas...
Benoit Izac
Le #23926171
Bonjour,

le 01/11/2011 à 14:22, pif a écrit dans le message

Peut-être, je ne connais absolument rien en théorie des graphes. Si tu
me dis que c'est indispensable pour résoudre mon problème, je veux bien
y jeter un ½il.



non, en informatique, on retrouve grossomodo deux structures des
données essentiellement: les espaces multidimensionner et les graphes
(réseau de transport de communication, sociaux, etc ...). T'as pas
besoin de connaitre la théorie des graphes, mais je t'en recommande la
lecture, c'est au programme de la première année d'IUT...

je mentionnais ca c'est c'est un terme on ne peut plus courant dans le
métier...



Je n'ai pas précisé : j'ai terminé mes études il y a plus de 15 ans et
je ne travaille pas dans l'informatique. J'admets donc bien volontiers
mes lacunes dans ce domaine et c'est pourquoi je demandais si ça avait
un quelquonque intérêt pour mon besoin.

[...]
Même remarque que précédemment et c'est justement ça mon problème,
lister tous les sites de la table de liaison, c'est facile mais faire la
liaison entre src et dst, je ne sais pas faire.



tu fais 2 jointures, c'est tout...



Par exemple avec la table link_site (site_id, link_id, side) ?

CREATE VIEW site_A SELECT * FROM link_site WHERE side = "A";
CREATE VIEW site_B SELECT * FROM link_site WHERE side = "B";
SELECT site_A.site_id AS site_A, site_B.site_id AS site_B
FROM site_A, site_B
WHERE site_A.link_id = site_B.link_id;

Je pense que c'est correct mais je ne sais pas le faire en une seule
requête.

Non, c'est différent, dans le cas de l'état civil, tu peux avoir soit
M ou F et tu n'as pas de contrainte. Si par contre tu prends un couple
(non homosexuel), c'est différent tu ne peux pas avoir deux M ou deux
F dans le même couple. Je veux éviter d'une part, d'avoir des
incohérences (deux bandes hautes dans le même lien, la somme des azimut
qui n'est pas égal à 360°), d'autre part de consommer de l'espace
lorsque ce n'est pas nécessaire. Je pense que seule la table à plat
(sans la table de liaison) me le permet.



l'espace te pose pas trop de question... une base correcte devrait
largement tenir ce que tu lui demande... je connais pas la volumétrie,
mais j'ai pas peur pour quelques champs vides...

la; je maitrise pas les questions métiers, donc c'est pas la peine
d'aller plus loin.. t'as les éléments de base, je t'ai expliqué ce
qu'on appelle champ calculé... c'est un attribut qui peut etre calculé
à partir des autres. A toi de voir si tu peux le faire ou pas...



Est-ce qu'une contrainte CHECK serait la solution pour éviter les
incohérences ?

--
Benoit Izac
pif34
Le #23926611
Le 01/11/2011 15:24, Benoit Izac a écrit :

je mentionnais ca c'est c'est un terme on ne peut plus courant dans le
métier...



Je n'ai pas précisé : j'ai terminé mes études il y a plus de 15 ans et
je ne travaille pas dans l'informatique. J'admets donc bien volontiers
mes lacunes dans ce domaine et c'est pourquoi je demandais si ça avait
un quelquonque intérêt pour mon besoin.



c'est bien ce que je pensais après ta réponse ;)


Par exemple avec la table link_site (site_id, link_id, side) ?

CREATE VIEW site_A SELECT * FROM link_site WHERE side = "A";
CREATE VIEW site_B SELECT * FROM link_site WHERE side = "B";
SELECT site_A.site_id AS site_A, site_B.site_id AS site_B
FROM site_A, site_B
WHERE site_A.link_id = site_B.link_id;



quand tu fais une jointure, c'est plus propre (lisible) de l'exprimer
avec un join plutot qu'avec un where et des "="... conformément à la
norme SQL ANSI

un create view, c'est pareil qu'un select :

si t'as une table lien avec src et dest:

create view v1 as select sa.*, sb.* from
lien ls
join site sa on ls.idsrc = sa.id
join site sb on ls.idtrg = sb.id

si t'as une table avec une orientation (donc deux lignes pour les deux
sites associés à un seul lien)

create view v2 as
select sa.*, sb.*
from lien_site lsa
join site sa on ls.id_site = sa.id

join lien_site lsb on lsa.id_lien = lsb.id_lien
and lsa.orientation = 1 and lsb.orientation = 0
join site sb on lsb.id_site = sb.id


Je pense que c'est correct mais je ne sais pas le faire en une seule
requête.

Est-ce qu'une contrainte CHECK serait la solution pour éviter les
incohérences ?



quelques incohérences ?
t'as des contraintes d'intégrité (unicité, etc. ) qui sont déjà
intéressantes... tu peux ajouter des contraintes checks, et meme faire
bien plus complexe en associant une fonction stockée à tes contraintes
check...

tu peux meme aller plus loin avec des triggers et du PL sql...
mais étant donné que t'es débutant en matière de SQL, je te recommande
d'y aller progressivement... commence pas bétonner ton schéma avec les
contraintes existantes, tu verras ensuite pour les check et triggers....
Publicité
Suivre les réponses
Poster une réponse
Anonyme