web-dev-qa-db-fra.com

Conception de base de données pour une relation récursive

Prenons le cas où j'essaie de modéliser une base de données pour une entreprise:

  • Entités: Employees, Managers, Departments.
  • Un Employee ne fonctionne que dans 1 Department, alors qu'un Department peut avoir de nombreux Employees dans celui-ci.
  • Un Manager peut gérer seulement 1 Department et de la même façon un Department peut avoir seulement 1 Manager.
  • Un 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).

First Solution

  • É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) Second solution

  • É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 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:

  1. Y a-t-il des erreurs évidentes dans la conception telle qu'elle est?
  2. Comment résoudre chaque problème dans les deux cas?
  3. Y at-il une meilleure solution que ces deux?
20
Songo

J'irais probablement avec quelque chose comme:

enter image description here

Ce modèle présente les caractéristiques suivantes:

  • Le gestionnaire "hérite" d'un employé .
    • Pour représenter un employé, insérez une seule ligne dans EMPLOYEE.
    • Pour représenter un responsable, insérez une ligne dans EMPLOYEE et une ligne dans MANAGER.
  • Un département peut avoir plusieurs employés.
  • Chaque service a exactement 1 responsable et chaque responsable gère 0 ou 1 service.
  • Un superviseur peut être un employé ordinaire ou un gestionnaire.
  • Les ministères ne sont pas obligés de "faire correspondre":
    • Un superviseur peut travailler dans un service différent de l'employé supervisé.
    • Un responsable peut gérer un département différent de l'endroit où il travaille.
    • Si un superviseur est responsable, le (s) département (s) qu’il gère, le (s) département (s) pour lequel il travaille et le (s) département (s) de ses employés supervisés peuvent tous être différents.

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:

enter image description here

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 ...

enter image description here

... 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.

25

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é!

1

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.

0
Diego

Je pense que c'est la meilleure solution:

DB Design

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.

0
pascalvgemert

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. 

0
Ellest