Soucis de conception de TABLE

ViPHP
ViPHP | 2291 Messages

27 déc. 2009, 14:02

Bonjour,

J'aimerais un avis concernant une conception de table.
Voilà l'idée j'ai des utilisateurs qui gêre des zone, donc j'ai un champs zone jusque là pas de soucis, par contre par zone il y a un chef
et là j'avais penser faire dans le même champ lui atribuer plusieurs zone séparer par une , exemple zone1, zone2, zone3.

Ensuite il me suffit de faire un explode() pour récupérer dans l'exemple ci-dessus 3 zones et de faire une boucle pour ma requete sql
exemple :
$Zone = explode(',', $rows['zone']);
$SqlZone = COUNT($Zone);

for ($i=0; $i<$SqlZone ; $i++){
$ReqSql .= "AND zone = '".$Zone[$i]."'";
}
Mais je suis pas certain que la méthode soit la meilleur, de là ma demande d'avis :wink:
De plus comme je suis dans la phase de test je peut encore changer n'importe quoi :roll:

D'avance merci
ImageCe que l'on apprend par l'effort reste toujours ancré beaucoup plus longtemps.

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

29 déc. 2009, 19:05

:afraid:

Pour les conceptions de base de données, il y a un recueil de règles permettant d'éviter de faire des erreurs de conception : Les formes normales.
Elles te permettent de ne pas faire d'erreur pouvant mettre en péril une base de données. (plus d'info : http://fr.wikipedia.org/wiki/Forme_norm ... ionnelles))

Et la 1ère forme normale dit :
1FN - première forme normale :
Respecte la première forme normale, la relation dont tous les attributs :
  • contiennent une valeur atomique (les valeurs ne peuvent pas être divisées en plusieurs sous-valeurs dépendant également individuellement de la clé primaire)
  • contiennent des valeurs non répétitives (le cas contraire consiste à mettre une liste dans un seul attribut).
  • sont constants dans le temps (utiliser par exemple la date de naissance plutôt que l'âge).
Le non respect de deux premières conditions de la 1FN rend la recherche parmi les données plus lente parce qu'il faut analyser le contenu des attributs. La troisième condition quant à elle évite qu'on doive régulièrement mettre à jour les données.
Donc, pour répondre à ta question, c'est effectivement une très mauvaise idée ;)

Selon ce que tu dis, ce que j'aurais mis en place est ce qui suit :
une table "utilisateur", une table "zone".
Entre les 2, une table d'association "utilisateur_zone" qui défini quels sont les utilisateurs qui gèrent une zone et quelles sont les zones gérées par un utilisateur (d'après ce que tu dis, je suis parti du fait qu'un utilisateur pouvait gérer plusieurs zones, et qu'une zone pouvait être géré par plusieurs utilisateur).
Ensuite, dans la table "zone", je mettrais une clé étrangère vers la table "utilisateur" qui défini l'utilisateur chef de la zone.

Ainsi, tu ne casses pas les formes normales, et en plus, tu respectes proprement les conditions de base.
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

ViPHP
ViPHP | 2291 Messages

29 déc. 2009, 19:14

:pouce: Merci je vais suivre ton idée.
Juste pour être certain de t'avoir comprid.
Exemple
Table Users
Users1
Users2
Users3

Table Zone
Zone1
Zone2

Dans l'exemple le Users1 a la Zone3
Le USers 2 A la zone 1
Et le Users3 A la zone 1 et 2

A partir de là comment construirais tu tes TABLES

D'avance merc
ImageCe que l'on apprend par l'effort reste toujours ancré beaucoup plus longtemps.

ViPHP
ViPHP | 2291 Messages

29 déc. 2009, 21:03

Salut,

Alors voilà en partant de ton idée, j'ai fais ceci j'ai créer une table sous_traitant , une table zone, et une table users.

La table sous_traitant reprend
les données de la zone qu'ils traitent.

La table Users reprend les données utilisateurs :wink:

Et une table zone qui elle prend les zone et utilisateur avec une liaison entre la table user et la table sous_traitant
CREATE TABLE IF NOT EXISTS `zone` (
  `id` int(5) NOT NULL AUTO_INCREMENT,
  `zone` int(5) NOT NULL,
  `user` int(5) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

--
-- RELATIONS POUR LA TABLE `zone`:
--   `user`
--       `users` -> `id_users`
--   `zone`
--       `sous_traitant` -> `id`
--

--
-- Contenu de la table `zone`
--

INSERT INTO `zone` (`id`, `zone`, `user`) VALUES
(1, 2, 1),
(2, 1, 2),
(3, 1, 3),
(4, 2, 3);

Donc dans cet exemple pour connaitre les zones d’un utilisateur il me suffit de faire
$SqlZone = "SELECT zn.zone, zn.user, st.id, st.gestion
                        FROM zone zn, sous_traitant st
                        WHERE zn.zone = st.id
                        AND zn.user = '".$_SESSION['id_user']."' ";
Par exemple, le schéma te semble correct ?
Modifié en dernier par dunbar le 29 déc. 2009, 21:42, modifié 2 fois.
ImageCe que l'on apprend par l'effort reste toujours ancré beaucoup plus longtemps.

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

29 déc. 2009, 21:30

Est-ce que tu pourrais me donner le schéma de toutes les tables ?
Parce que je crains de voir que tu pars mal. :?
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

30 déc. 2009, 15:25

Je t'ai fait peur ?
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

ViPHP
ViPHP | 2291 Messages

30 déc. 2009, 16:52

Oui :evil:
Non mais je voulais voir ci je pouvais faire autrement voici mes tables :
CREATE TABLE IF NOT EXISTS `users` (
  `id_users` int(2) NOT NULL AUTO_INCREMENT,
  `login` varchar(20) NOT NULL,
  `password` varchar(40) NOT NULL,
  `grade` int(5) NOT NULL,
  `prenom` varchar(20) NOT NULL,
  `nom` varchar(20) NOT NULL,
  `tel` varchar(25) NOT NULL DEFAULT 'Aucun',
  `mail` varchar(40) NOT NULL,
  `sc` varchar(20) NOT NULL,
  `zone` int(1) NOT NULL,
  `gestion` varchar(50) NOT NULL,
  `region` varchar(20) NOT NULL,
  PRIMARY KEY (`id_users`),
  KEY `pseudo` (`login`),
  KEY `password` (`password`),
  KEY `zone` (`zone`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
CREATE TABLE IF NOT EXISTS `sous_traitant` (
  `id` int(5) NOT NULL AUTO_INCREMENT,
  `sc` varchar(30) NOT NULL,
  `gestion` varchar(10) NOT NULL,
  `compteur` varchar(15) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
Voilà :wink:

Et d'avance merci
ImageCe que l'on apprend par l'effort reste toujours ancré beaucoup plus longtemps.

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

30 déc. 2009, 17:22

Est-ce que tu pourrais, maintenant, m'expliquer qui gère quoi ?

Si je comprend bien, tu as des users, des sous-traitants, et les users gèrent les sous-traitants (table zone), et chaque sous-traitant à un user chef ?
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

ViPHP
ViPHP | 2291 Messages

30 déc. 2009, 17:47

Explication en gros :wink:

Il y a des zones -> (des communes, plusieurs communes constituent une zone) en général 1 technicien par zone.

Donc par exemple un sous traitant introduit une demande de travail et suivant la commune introduite ça arrive directement dans l'interface du technicien de la zone.

Il y a gestion (qui en réalité pourrait être un département en FRANCE) plusieurs techniciens mais un seul sous traitant.

Donc l'idée :
Une TABLE user :
le champ zone correspond a une commune, (j'ai un fichier avec des codes postaux auquel j'ai donner des numéros pour relier les zones aux techniciens)
le champs gestion correspond aux sous traitant attacher aux techniciens.

La table sous traitant:
SC uniquement le nom de la société
Gestion qui reprend qui est le même que dans la table users
compteur qui lui sert a la numérotation des demande de travail (chaque sous traitant a sa propre numérotation, et je ne sais pas changer ça sinon ça irais tout seul :wink: )
Donc a chaque nouvelle demande je regarde dans la table compteur du sous traitant.

Exemple :
Sous traitant 1 est PHPFRANCE donc la numérotation serais PHPFR-2009-0
Sous traitant 2 DUNBAR donc lui DUN-2009-0
etc...



Mon seul réel soucis que qu'ils y a des techniciens chef qui doivent pouvoir être relié a plusieurs sous traitant, bien qu’avec la table zone je pense avoir résolu mon soucis ?
ImageCe que l'on apprend par l'effort reste toujours ancré beaucoup plus longtemps.

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

30 déc. 2009, 18:40

Alors, ce que j'aurais fait, avec le détail de ma méthodologie :

Tout d'abord, les entités
  • les utilisateurs (technicien)
  • les zones
  • les sous-traitants
Comme chacune de ces entités à des données propres (qui ne dépendent pas des autres), je ferais donc une table pour chaque entité, soit 3 tables "user", "zone" et "sous-traitant"

Ensuite, les relations
Si je tente de résumer les relations, grâce à tes postulats, j'arrive à cette liste de relations :
  • Un ou plusieurs techniciens (user) peuvent gérer une zone, un technicien peut gérer plusieurs zones (relation n:m entre user et zone)
  • un sous-traitant peut déposer une demande pour une seule zone (relation 1:n entre zone et sous-traitant)
  • une zone peut avoir des demandes de plusieurs sous-traitant (relation n:m entre zone et sous-traitant)
  • un sous-traitant à un user associé directement (cette clause me parait bizarre, si tu pouvais me la confirmer. Je pense qu'il s'agit plus du user responsable d'une zone, dans le cas où il y en a plusieurs)(relation 1:n entre user et sous-traitant)
Du coup, je pense utiliser le schéma suivant :
Image

Du coup, de là, tu peux gérer tes zones, tes users, tes sous-traitants, puis ensuite, les associer entre eux.
Lorsque qu'un sous-traitant veut déposer une demande, on regarde sa zone grace à "sous-traitant.zone_idzone" puis on crée une ligne dans la table "demande".
Pour connaitre les users agissant sur une zone, on regarde dans la table "user_zone".
Pour savoir quel est le technicien responsable d'un sous-traitant, on regarde le champ "sous-traitant.user_iduser"

N'hésites pas à revenir vers moi si ce n'est pas clair, où si j'ai mal compris ton besoin de base.
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

ViPHP
ViPHP | 2291 Messages

30 déc. 2009, 18:46

Merci a toi, je vais étudié ta proposition
Merci encore :wink:
ImageCe que l'on apprend par l'effort reste toujours ancré beaucoup plus longtemps.