Conception de base de données pour une relation récursive
voici un cas où je suis en train de modéliser une base de données pour une société:
- Entités:
Employees
,Managers
,Departments
. Employee
ne fonctionne que chez 1Department
Department
peut avoir de nombreuxEmployees
travailler dessus.Manager
peut gérer que 1Department
et mêmeDepartment
peut avoir seulement 1Manager
.Manager
supervise de nombreuxEmployees
, maisEmployee
n'est supervisé par unManager
.
Maintenant, j'ai 2 possibilités pour ce modèle:
première solution:
je considérerai que le Manager
entité hérite de la Employee
entité considérant que je vais conserver des données qui sont uniques aux gestionnaires (par exemple Bonus & Status).
puisque la relation entre
Department
etEmployee
1:N
alors je vais mettre leDepartment Id
clé étrangère dans l'Employee
tableauWorks
relation.puisque la relation entre
Department
etManager
1:1
alors je vais mettre leDepartment Id
clé étrangère dans l'Manager
tableauManages
relation.
problème: comment représenter la relation récursive entre Manager
et Employee
?
Deuxième solution:
je considérerai que le Manager
entité n'est pas nécessaire que d'autres Employees
peut aussi avoir un Bonus
et Status
. (En fait j'ai ajouté ces 2 attributs juste pour voir comment le modéliser dans les deux cas)
- puisque la relation entre
Department
etEmployee
1:N
alors je vais mettre leDepartment Id
clé étrangère dans l'Employee
tableauWorks
relation. - puisque la relation entre
Employee
etManager
1:N
alors je vais mettre leEmployee Id
clé étrangère dans l'Employee
tableauSupervises
rapport et appelleManager Id
.
problème: comment représenter la relation entre les Manager
et <!--4?
Questions:
- Est-il des erreurs évidentes dans la conception comme ils sont?
- Comment résoudre le problème dans les deux cas?
- Est-il mieux la solution de ces deux?
5 réponses
je dirais probablement quelque chose comme:
Ce modèle présente les caractéristiques suivantes:
- le directeur "hérite" l'employé.
- pour représenter un employé, inscrire une seule ligne dans employé.
- pour représenter un gestionnaire, inscrire une ligne dans employé et une rangée de MANAGER.
- un ministère peut avoir plusieurs employés.
- chaque ministère a exactement 1 gestionnaire et chaque gestionnaire gère 0 ou 1 départements.
- Un superviseur peut être employé ordinaire ou d'un gestionnaire.
- les ministères ne sont pas tenus de " jumeler":
- Un superviseur peut travailler dans différents département de l'encadrement de l'employé.
- un gestionnaire peut gérer un service différent de celui où il travaille.
- Si un superviseur est responsable, le département (s)il gère, le département (s)il travaille dans et le ministère(s) de ses employés dirigés peuvent tous être différents.
Remarque: Si votre SGBD ne supporte pas les contraintes différées, vous voudrez faire le ministère.MANAGER_ID NULL-able, pour briser le cycle qui vous empêcherait autrement d'insérer les nouvelles données.
si les ministères doivent apparier, alors vous utiliserez une technique propre au SGBD (comme des déclencheurs ou des contraintes "spéciales"), ou "propagerez" DEPARTMENT_ID dans le PK des employés. Cette propagation est ce qui permet finalement l'appariement:
puisque EMPLOYEE_ID doit être globalement unique, il ne peut pas rester dans la clé composite avec le DEPARTMENT_ID. Donc, nous le faisons alternativement clé et à la place d'utiliser la mère porteuse EMPLOYEE_NO dans le PK.
Ce modèle vous empêche d'avoir un gestionnaire qui gère un ministère et travaille dans un autre, ou un superviseur qui supervise les employés à partir d'un autre département.
Dans le cas où vous n'êtes pas familier avec 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 L'employé et le gestionnaire.
sans entrer dans les détails, je vous assure que la solution employé/Gestionnaire/service est, à long terme, une source de mécontentement (d'abord) puis une véritable PITA (plus tard) pour les personnes en charge de la maintenance de la base de données et/ou du développement de son interface. Je vous conseille donc de vous en tenir à votre deuxième proposition.
en ce qui concerne la relation gestionnaire/ministère, vous avez principalement deux façons de représenter cette relation. Les deux solutions vous autorisent à garder votre récursif "Le Gestionnaire Gère la relation avec L'employé" en plus d'une relation "le gestionnaire gère le ministère" que vous pouvez mettre en œuvre comme suit:
1-first/simple way: ajouter un ID de gestionnaire/employé dans votre table de département. Ce champ est bien sûr une clé étrangère à la table des employés
2 - seconde/solution plus complexe: ajouter une table "manager" avec les champs suivants:
Manager id (PK, surrogate)
Department id (FK)
Employee id (FK)
beginningDate
endingDate
où vous stockerez l'historique de gestion: qui, pour quel département, à partir de quand, jusqu'à lorsque
dans ce cas, n'oubliez pas d'ajouter de la logique (déclencheur, ou contrôle côté client) pour traduire vos règles d'affaires comme vous ne pouvez avoir qu'un seul gestionnaire pour une période spécifique et un ministère spécifique, aucun ministère ne peut rester plus de ... sans gestionnaire, etc.
EDIT:
Position id (PK, surrogate)
Department id (FK)
Employee id (FK)
Position Level (FK)
beginningDate
endingDate
où le "niveau de poste" mène à une autre table qui occupe les différents postes qui peuvent exister dans un ministère, l'un d'entre eux étant évidemment le poste de "gestionnaire".
cette proposition est plus proche de ce qui est utilisé dans la base de données et les logiciels de RH, et vous pourriez ne pas avoir besoin d'une solution aussi complexe. Mais gardez à l'esprit que diviser les êtres humains en plusieurs tables est Toujours une erreur.
EDIT: suite à vos commentaires ...
pour clarifier les choses, je vous conseille d'ajuster vos noms de champ. Je vous propose d'avoir les champs suivants:
Tbl_Employee.id_EmployeeManager
et
Tbl_Department.id_DepartmentManager
en faisant cela, nous (ou n'importe quel développeur) comprendrons immédiatement que id_EmployeeManager participe à la relation récursive entre les personnes, tandis que id_departmanager participe à la relation entre les personnes et ministère.
retournez à vos questions, et selon moi, vous ne devez pas créer le lien suivant:
Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_EmployeeManager
ce faisant, vous voulez dire que quelqu'un ne peut pas être un gestionnaire de département à moins que il gère déjà des employés. Que sur les départements avec un seul employé? Qu'en est-il des personnes nommées gestionnaires d'un ministère nouvellement créé, où aucun employé n'est encore affecté? Il ne fonctionne pas. Le bon lien devrait être:
Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_Employee
vous pouvez bien sûr ajouter quelques règles d'affaires disant par exemple que "un employé qui gère un ministère ne peut être qu'un gestionnaire" (id_Employee existe quelque part comme id_EmployeeManager) ou "un employé qui gère un ministère ne peut pas avoir de gestionnaire (où id_EmployeeManager pour cet employé est null...). Mais ce ne sont que des règles commerciales. Votre modèle de données est propre à accepter toutes les règles, tant que la règle de base est respecté, qui est qu'un département est géré par un employé!
je pense que c'est la meilleure solution:
un gestionnaire est Un employé qui gère un département. La relation récursive, vous pouvez obtenir par le suivant:
L'employé a un ministère Un ministère a un employé comme gestionnaire
peut-être est-il pratique de donner à la table des employés une colonne EmployeeType pour définir le rôle.
Mon avis:
personne de Table où vous ajouterez l'information pour les employés et les gestionnaires, les gestionnaires sont des êtres humains aussi, vous savez? :), et vous avez un champ managerId à lier à L'Id du manager.
Table de service avec le ministère de l'information
et, si l'employé peut appartenir à plus d'un ministère, créer une table employee_department pour les relier. Si un employé ne peut appartenir qu'à un seul ministère et que vous n'avez pas besoin de plus d'information la relation, ajouter un champ departmentID sur la table de L'employé.
pourquoi ne pas s'en tenir à la deuxième conception et avoir une pseudo-relation?
je suppose que vous allez avoir un department_id
colonne dans l'entité de L'employé pour lier la relation entre l'employé et les entités du Ministère. Si nous pouvons supposer qu'il n'y aura pas de hiérarchie de MANAGERS (managers of managers) nous pouvons imposer une pseudo-relation entre les deux tables où Department_ID
pour les gestionnaires (Manager_ID
Null) représente le Ministère qu'ils gèrent.
aussi longtemps que vous documentez cela clairement, je pense que ce serait une approche peu encombrante puisque vous auriez déjà une colonne FK (department_id
) dans l'entité de L'employé faisant référence à l'entité du Ministère.