Prenons le cas où j'essaie de modéliser une base de données pour une entreprise:
Employees
, Managers
, Departments
.Employee
ne fonctionne que dans 1 Department
, alors qu'un Department
peut avoir de nombreux Employees
dans celui-ci.Manager
peut gérer seulement 1 Department
et de la même façon un Department
peut avoir seulement 1 Manager
.Manager
supervise plusieurs Employees
, mais un Employee
n'est surveillé que par un Manager
.Maintenant, j'ai deux façons de modéliser cela:
Première solution:
Je considérerai que l'entité Manager
hérite de l'entité Employee
en considérant que je conserverai des données propres aux gestionnaires (par exemple, Bonus & Statut).
Étant donné que la relation entre Department
et Employee
est 1:N
, je mets alors le Department Id
comme clé étrangère dans la table Employee
pour la relation Works
Étant donné que la relation entre Department
et Manager
est 1:1
, je mets alors le Department Id
comme clé étrangère dans la table Manager
pour la relation Manages
Problème: Comment puis-je représenter la relation récursive entre Manager
et Employee
?
Deuxième solution:
Je considérerai que l'entité Manager
n'est pas nécessaire, car les autres Employees
peuvent également avoir un Bonus
et Status
. (En fait, j'ai ajouté ces 2 attributs pour voir comment le modéliser dans les deux cas)
Department
et Employee
est 1:N
, je mets alors le Department Id
comme clé étrangère dans la table Employee
pour la relation Works
Employee
et Manager
est 1:N
, je mets alors le Employee Id
en tant que clé étrangère dans la table Employee
pour la relation Supervises
Et je l'appelle Manager Id
. Problème: Comment puis-je représenter la relation entre Manager
et Department
?
Des questions:
J'irais probablement avec quelque chose comme:
Ce modèle présente les caractéristiques suivantes:
REMARQUE: Si votre SGBD ne prend pas en charge les contraintes différées, vous voudrez rendre DEPARTMENT.MANAGER_ID NULL-capable pour rompre le cycle qui vous empêcherait sinon d'insérer les nouvelles données.
Si les services doivent correspondre, utilisez une technique spécifique au SGBD (comme les déclencheurs ou les contraintes "spéciales") ou "propagez" le DEPARTMENT_ID dans la PK des employés. Cette propagation est ce qui permet finalement la correspondance:
EMPLOYEE_ID devant être globalement unique, il ne peut pas rester dans la clé composite avec le DEPARTMENT_ID. Nous utilisons donc la clé de substitution EMPLOYEE_NO dans la PK, à la place de la clé alternative.
Ce modèle vous évite d'avoir un responsable qui gère un département et travaille dans un autre, ou un superviseur qui supervise les employés d'un autre département.
Si vous ne connaissez pas le symbole ...
... il dénote une "catégorie". Dans ce contexte, vous pouvez simplement l'interpréter comme une relation "1 à 0 ou 1" entre EMPLOYEE et MANAGER.
Sans entrer dans les détails, je vous assure que la solution Employee/Manager/Department est, à long terme, une source de mécontentement (d'abord) puis un véritable PITA (plus tard) pour les responsables de la maintenance de la base de données et/ou en développant son interface. Je vous conseille donc de vous en tenir à votre deuxième proposition.
En ce qui concerne la relation gestionnaire/service, vous avez principalement deux façons de représenter cette relation. Les deux solutions vous autorisent à conserver votre relation récursive "Le gestionnaire gère l'employé" en plus d'une relation "Le gestionnaire gère le service" que vous pouvez implémenter de la manière suivante:
1 - premier moyen/simple: ajoutez un identifiant de responsable/employé dans votre table des départements. Ce champ est bien sûr une clé étrangère à la table employee
Solution 2-seconde/plus complexe: ajoutez une table "manager" avec les champs suivants:
Manager id (PK, surrogate)
Department id (FK)
Employee id (FK)
beginningDate
endingDate
où vous allez stocker l'historique de gestion: qui, pour quel département, de quand, jusqu'à quand
Dans ce cas, n'oubliez pas d'ajouter une logique (déclencheur ou contrôle côté client) pour traduire vos règles métier, par exemple, vous ne pouvez avoir qu'un seul responsable pour une période et un service spécifiques. Aucun service ne peut rester plus de ... sans manager, etc.
MODIFIER:
3 - une solution plus riche consisterait à généraliser ma deuxième proposition et à vous permettre de suivre l'évolution de la carrière de chacun dans l'entreprise. Vous pouvez le faire avec un tableau 'works in', tel que celui-ci (comme nous l'appelons ici un tableau 'position', je garderai la même terminologie ici:
Position id (PK, surrogate)
Department id (FK)
Employee id (FK)
Position Level (FK)
beginningDate
endingDate
Où "niveau de poste" conduit à une autre table occupant les différents postes pouvant exister dans un département, l'un d'eux étant bien entendu le poste de "responsable".
Cette proposition est plus proche de ce qui est utilisé dans la base de données et le logiciel RH, et vous n’avez peut-être pas besoin d’une solution aussi complexe. Mais gardez à l'esprit que diviser les êtres humains en plusieurs tables est TOUJOURS une erreur.
EDIT: suite à votre commentaire ...
Pour que les choses soient claires, je vous conseillerais d’ajuster vos noms de champs. Je vous proposerais les champs suivants:
Tbl_Employee.id_EmployeeManager
et
Tbl_Department.id_DepartmentManager
En faisant cela, nous (ou tout développeur) comprendrons immédiatement que id_EmployeeManager participe à la relation récursive entre les personnes, alors que id_DepartmentManager participe à la relation entre les personnes et le service.
Retour à vos questions, et selon moi, vous ne devriez pas créer le lien suivant:
Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_EmployeeManager
En faisant cela, vous voulez dire que quelqu'un ne peut pas être chef de serviceà moins queil gère déjà des employés. Qu'en est-il des départements avec un seul employé? Qu'en est-il des personnes nommées responsables d'un département nouvellement créé, où aucun employé n'est encore affecté? Ça ne marche pas. Le bon lien devrait être:
Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_Employee
Vous pouvez bien sûr ajouter des règles de gestion indiquant par exemple qu'un "employé gérant un département ne peut être qu'un responsable" (id_Employee existe quelque part sous le nom id_EmployeeManager) ou qu'un "employé gérant un département ne peut pas avoir de responsable (id_EmployeeManager pour cet employé est nul ...). Mais ce ne sont que des règles de gestion. Votre modèle de données est propre à accepter toutes les règles tant que la règle de base est respectée, à savoir qu'un département est géré par un employé!
Mon avis:
Table Personne où vous allez ajouter les informations pour les employés et les gestionnaires, les gestionnaires sont également des êtres humains, vous savez? :) et vous avez un champ managerId à associer à l'ID du manager.
Table department avec les informations de département
et, si l'employé peut appartenir à plus d'un service, créez une table employee_department pour les relier. Si un employé ne peut appartenir qu'à un seul département et que vous n'avez pas besoin de plus d'informations dans la relation, ajoutez un champ departmentID dans la table Employee.
Je pense que c'est la meilleure solution:
Un responsable est un employé qui gère un service . La relation récursive que vous pouvez obtenir par le flux suivant:
Un employé a un département Un département a un employé en tant que manager
Peut-être est-il utile de donner à la table employee une colonne EmployeeType pour définir le rôle.
Que diriez-vous de vous en tenir à la deuxième conception et d'avoir une pseudo-relation?
Je suppose que vous allez avoir une colonne department_id
dans l'entité Employé pour relier la relation entre les entités Employé et Service. Si nous pouvons supposer qu'il n'y aura pas de hiérarchie de gestionnaires (gestionnaires de gestionnaires), nous pouvons imposer une pseudo-relation entre les deux tables où Department_ID
pour les gestionnaires (Manager_ID
est Null) représente le service qu'ils gèrent.
Tant que vous documentez ceci clairement, je pense que ce serait une approche peu encombrante puisque vous auriez déjà une colonne FK (department_id
) dans l'entité Employé référençant l'entité Département.