2010-03-19 8 views
6

Remarqueconception de base de données SQL Server 2005 - plusieurs à de nombreuses relations avec la hiérarchie

J'ai complètement ré-écrit mon message d'origine pour mieux expliquer le problème que je suis en train de comprendre. J'ai essayé de généraliser le problème autant que possible.

Aussi, mes remerciements aux personnes originales qui ont répondu. J'espère que ce message rend les choses un peu plus claires.

Contexte

En bref, je me bats pour comprendre la meilleure façon de concevoir une base de données à petite échelle pour gérer (ce que je perçois être) plusieurs nombreux à plusieurs.

Imaginez le scénario suivant pour une structure organisationnelle de l'entreprise:

   Textile Division     Marketing Division 
        |          | 
      ----------------------    ---------------------- 
      |     |    |     | 
     HR Dept   Finance Dept  HR Dept   Finance Dept 
      |     |    |     | 
     ----------   ----------  ----------   --------- 
    |   |   |  |  |  |   |  | 
    Payroll  Hiring Audit  Tax Payroll Hiring  Audit Accounts 
    |   |   |  |  |  |   |  | 
    Emps  Emps  Emps  Emps Emps  Emps  Emps Emps  

NB: Emps indique une liste de employess qui travaillent dans ce domaine

Quand j'ai commencé avec cette question que j'ai fait quatre tableaux distincts :

  1. Divisions -> Textile, marketing (PK = DivisionID)
  2. Departments -> RH, Finance (PK = DeptID)
  3. Functions -> paie, recrutement, vérification, de fiscalité, de la comptabilité (PK = FunctionID)
  4. Employees -> Liste de tous les employés (PK = EmployeeID)

Le problème que je vois est qu'il ya plusieurs nombreux à àplusieurs-à-dire de nombreux ministères ont beaucoup de divisions et de nombreuses fonctions ont beaucoup de départements.

Question

Donner la structure de base de données ci-dessus, supposons que je voulais faire ce qui suit:

  • Obtenez tous les employés qui travaillent dans la fonction de la paie de la Division du marketing

Pour ce faire, je dois être en mesure de faire la différence entre les deux départements de la paie, mais je ne suis pas sûr comment cela peut être fait?

Je comprends que je pouvais construire une table « Link/Junction » entre les ministères et les fonctions afin que je puisse récupérer quelles sont les fonctions dont les ministères. Cependant, j'aurais encore besoin de différencier la division à laquelle ils appartiennent.

Effort de recherche

Comme vous pouvez le voir, je suis un civilisatrices en matière de base de données deisgn. J'ai passé les deux derniers jours à résoudre ce problème, à travers des modèles de jeux imbriqués, des modèles de contiguïté, à lire que ce problème est connu pour ne pas être complet, etc. Je suis sûr qu'il existe une solution simple?

+0

oui, il y a une solution, pas de soucis.les ensembles imbriqués pourraient le faire (mais pourraient être une overkill). pourriez-vous s'il vous plaît définir si vous voulez travailler avec des hiérarchies générales de n'importe quel niveau ou savez-vous que ce sera hiérarchie à 3 niveaux? – Unreason

+0

@Goran - pour le moment, ce sera une hiérarchie à 3 niveaux seulement. –

+0

ok, alors pour le moment ma réponse est toujours là. :) – Unreason

Répondre

2

Basé sur le post mis à jour, et en faisant quelques hypothèses (assez évidentes) basées sur les noms utilisés, je propose ce qui suit.Il y a quatre entités:

  • Divisions
  • Départements
  • Fonctions
  • Entités

Il y a beaucoup de relations entre ces entités. Peu d'entre eux sont hiérarchiques, la plupart sont des associations simples:

  • Option A1: Il existe une liste principale de fonctions. Chaque département peut effectuer (ou faire) une ou plusieurs fonctions, et une fonction peut être effectuée par plus d'un département.
  • Option A2: Les fonctions sont «détenues» par les ministères. Aucune fonction ne peut être effectuée par deux ou plusieurs départements. (Cela semble être le cas, comme le département RH a la paie et l'embauche, et le département des finances a Audit, Tax et comptes.)

  • Les fonctions sont exécutées par les ministères pour (au nom) divisions. (Le service RH s'occupe de la paie et de l'embauche pour les divisions Textile et Marketing, tandis que le département des finances fait de la vérification et de la fiscalité - mais pas des comptes - pour la division Textile et Audit and Accounts - mais pas pour la division Marketing). Plus précisément, les départements exécutent des fonctions sélectionnées pour les divisions sélectionnées auxquelles ils sont associés, et cette association est définie par leur performance de cette fonction. Au-delà de l'exécution du travail des fonctions, il ne semble pas y avoir de relation entre les départements et les divisions. Il n'y a pas de relation hiérarchique entre eux, car on ne «possède» ni ne contient l'autre.

Cela conduit à ces gros esquissés tables:

-- Division ----- 
DivisionId (primary key) 

-- Department --- 
DepartmentId (primary key) 

-- Function ----- (assumes option A2) 
FunctionId (primary key) 
DepartmentId (foreign key, references Department) 

-- DivisionFunctions ---- 
DivisionId (First column of compound primary key) 
FunctionId (Second column of compound primary key) 

(Vous pouvez éventuellement inclure une clé de substitution pour identifier chaque ligne, mais DivisionId + functionId travaillerais.)

Il est pas assez de matériel ici à entièrement décrivent comment "les employés" s'intègrent dans le modèle. Étant donné que les employés font le travail des fonctions: un employé peut-il faire le travail de plus d'une fonction, ou ne fait-il que le seul? Est-ce qu'un employé fait le travail de la fonction, peu importe la ou les divisions pour lesquelles il est fait, ou est-ce qu'il est assigné à faire le travail pour une ou plusieurs divisions? Deux options évidentes ici, bien que des variantes plus complexes sont possibles:

  • Option B1: Les employés font le travail d'une ou plusieurs fonctions au sein des ministères, et d'effectuer ce travail pour toutes les divisions qui exigent que la fonction de ce ministère.
  • Option B2: Les employés sont affectés à une fonction spécifique pour une division spécifique.

Compte tenu de ces tables pourraient ressembler à:

-- Employee ----- (assumes option B1) 
EmployeeId (primary key) 
DepartmentId (foreign key, references Department) 

-- EmployeeFunction ----- (assumes option B1) 
EmployeeId (First column of compound primary key) 
FunctionId (Second column of compound primary key) 

... et donc tous les employés qui peuvent effectuer une fonction effectuera pour toutes les divisions ont besoin.Ou,

-- Employee ----- (assumes option B2) 
EmployeeId (primary key) 
DepartmentId (foreign key, references Department) 

-- EmployeeAssignment ----- (assumes option B2) 
EmployeeId (foreign key, references Employee) 
DivisionId (first of two-column foreign key referencing DivisionFunctions) 
FunctionId (second of two-column foreign key referencing DivisionFunctions) 

(ou, au lieu de DivisionId et functionId, comprennent la clé de substitution optionnelle de DivisionFunctions.) ... et donc les employés sont affectés individuellement à des fonctions à exécuter par le ministère pour une division.

Mais cela laisse encore beaucoup de questions «et si et quand»: Est-ce que les employés «appartiennent» aux départements? Les employés peuvent-ils appartenir à (travailler pour) plusieurs départements? Peut-être que les employés appartiennent à des divisions? Suivez-vous les fonctions qu'un employé peut accomplir, même s'il ne le fait pas actuellement? De même, suivez-vous le département pour lequel un employé travaille, même s'il est actuellement «entre les fonctions»? Si un employé peut effectuer les fonctions A et B, et qu'une division a besoin de ces deux fonctions, un employé peut-il être affecté à effectuer seulement A et non B pour cette division?

Il y a une recherche de plus de besoins à faire ici, mais je voudrais penser que c'est un bon début.

+0

Philip - Grande réponse complète. Je pense que je pourrais vraiment utiliser ceci pour augmenter ma pensée et approche - je digérerai ceci au cours des prochaines 24 heures. Note rapide - les employés ne peuvent travailler que pour une fonction. Ils ne peuvent pas travailler pour plusieurs fonctions ou divisions. –

1

Eh bien, vous ne mettriez pas tout cela dans une seule table. Vous devez lire sur la normalisation des données et des jointures. (Et ne jamais stocker quelque chose dans une liste délimitée par des virgules.)

Aucune base de données ne vaut son sel aurait le moindre problème à gérer un million d'enregistrements, c'est une base de données minuscule.

Vous avez besoin de tables pour les fonctions, les cours, les emplacements, les personnes, l'organisation et éventuellement certaines tables de jointure pour accommoder de nombreuses relations. Mais rien de tout cela n'est difficile ou même au-delà d'un design très basique. Je recommande que, avant de faire quoi que ce soit, vous obtenez un livre sur votre base de données choisie et lire sur les bases.

+1

+1 pour la dernière phrase, en recommandant certains livres de design DB. –

+0

HLGEM - J'ai édité mon article original pour rendre les choses un peu plus claires car je pense que j'ai peut-être quelque peu confondu au départ. BTW, commandé «SQL pour Smarties» par Celko. J'utilise SQL Server 2005 - tous les livres que vous recommanderiez? –

+0

Nous avons sauté 2005, donc je n'ai pas ce livre, mais on dirait qu'il a ce dont vous avez besoin http://www.amazon.com/Server-2005-Database-Design-Optimization/dp/1590595297/ref= sr_1_1? ie = UTF8 & s = livres & qid = 1269020643 & sr = 1-1 # noop – HLGEM

0

Essayez de donner à chaque entité une table de son propre exemple

//Table Structure 
location 
    locationId 
    name 

division 
    divisionId 
    name 
    locationId (fk => location) 

department 
    deparmentId 
    name 
    divisionId (fk => division) 

function 
    functionId 
    name 
    departmentId(fk => department) 

jobrole 
    jobroleId 
    name 
    functionId 

course 
    courseID 
    name 

jobrole_course_requirement 
    jobroleID 
    courseID 

employee 
    employeeID 
    name 

employee_jobRole 
    employeeID 
    jobRoleId 

emploeyee_course_attendance 
    emploeyee_course_attendanceID 
    emploeyeeID 
    courseID 
    dateAttended 

Et certains échantillon sélectionne

// Get course requirements for an employee 
select course.name 
    from course, 
     jobrole_course_requirement, 
     employee_jobRole 
    where 
     employee_jobRole.employeeID = 123 and 
     jobrole_course_requirement.JobRoleId = employee_jobRole.JobRoleId 
     course.courseID = jobrole_course_requirement.courseID 
+0

David - J'ai édité mon article original pour rendre les choses un peu plus claires car je pense que j'ai peut-être quelque peu confondu au départ. –

0

En général, quand je vais mettre en place un db, je viens avec quelles entités j'ai besoin et comment ils sont liés les uns aux autres (c'est-à-dire plusieurs-un, un-un, ...). Ce que vous semblez avoir fait. Alors, je vois ce que chaque entité aura besoin. Par exemple, Location peut avoir: locationid, address, ... Ensuite, Divisions En supposant qu'il y ait un emplacement pour plusieurs divisions, vous pourriez avoir l'entité de division ayant un ID de division, locationid, l'information dont chaque division a besoin. Donc, fondamentalement, si c'est une relation un-plusieurs comme un emplacement à plusieurs divisions, vous pouvez simplement mettre l'ID de l'emplacement dans la table de division. Cependant, s'il s'agit d'une relation multiple, il est probablement préférable d'avoir une table intermédiaire pour connecter les deux, de sorte que vous n'avez pas besoin d'avoir des enregistrements en double avec seulement un changement d'identifiant.

+0

John - J'ai édité mon article original pour rendre les choses un peu plus claires car je pense que j'ai peut-être quelque peu confondu au départ. –

1

Vous avez besoin d'une simple relation étoile. Le Position (table de faits) a juste ID des tables principales connexes (Département, Division etc). Cela permet d'utiliser n'importe quelle combinaison de tables principales

Les tables principales peuvent avoir une hiérarchie simple intégrée dans chacune d'elles si nécessaire. Et peuvent se rapporter au besoin. Mais le détail de cela n'affecte pas les requêtes sur Position

Vous pouvez faire les ID dans Position annulable pour les relations en option

Vous pouvez ajouter des colonnes StartDate et EndDate à Position pour suivre les changements au cours temps

Un exemple simple de ceci est:

SQL Table Diagram http://img52.imageshack.us/img52/3484/sqldiag1.jpg

+0

Je crois que votre solution n'est pas complètement normalisée - par exemple Finance in Marketing n'a pas d'impôt et Finance dans Textile n'a pas de compte. C'est quelque chose que votre modèle ne peut pas refléter. Votre solution est normalisée uniquement s'il n'y a pas de dépendances fonctionnelles entre DepartmentID, FunctionID, EmployeeID (si elles sont indépendantes) Correction – Unreason

+0

: cela était supposé être DepartmentID, FunctionID et DivisionID – Unreason

+0

Duh! C'est un échantillon pour montrer les possibilités. Vous pouvez ajouter des dépendances si nécessaire (exemple affiché pour département et division). Nous n'avons pas assez d'informations pour le rendre entièrement * normalisé *, @Remnant peut simplement ajouter une relation de département à fonction, etc – TFD

0

Peut-être (probablement) vous devriez considérer le département RH de la division Textile comme un département différent du département RH de la division Marketing.

1

Comme vous « civilisatrices » :), une chose à faire avant toute tentative de se sentir à la maison avec la conception de base de données est lu sur la normalisation, et de comprendre complètement toutes les formes normales jusqu'à 5NF

Si vous voulez modèle qui
1. les ministères sont dans les divisions
2. fonctions sont exécutées dans les services
3. les employés exécutent des fonctions

et que toutes les fonctions sont exécutées dans tous les départements, ni tous les départements sont tous divisions En vous devez stocker ce fait quelque part.

Tout en faisant la conception logique, donner à vos tables des noms descriptifs, de sorte que certains départements sont dans les divisions

departments_in_divisions 
candidate key: department, division 

alors vous avez des fonctions dans certains départements

functions_departments_divisions 
candidate key: function, department, division 
references: (department, division) in departments_divisions 

alors les employés ont des fonctions de certains départements et divisions

employees_function_department_division 
candidate key: employee, function, department, division 
references: (function, department, division) in functions_departments_divisions 

Afte r (ou avant cela) vous avez 3 autres entités fonctions, départements et divisions qui répertorieraient tous les départements, divisions et fonctions possibles qui seraient également référencés par les tables ci-dessus (ceci pourrait ne pas être complètement normalisé).

Aussi les noms des entités (tables) peuvent devenir quelque chose de plus approprié pour vous (vous seul pouvez connaître la sémantique complète du modèle de vos données). Surtout si vous remarquez que vous devez leur assigner d'autres attributs (champs).

Les valeurs pour les départements, divisions et fonctions sont leurs noms, il n'y a pas encore d'identifiants artificiels dans l'analyse ci-dessus. Vous pouvez les introduire dans l'étape suivante, après la modélisation physique vient la modélisation physique, ou vous pouvez garder les clés naturelles. Si vous allez avec des clés artificielles qui peuvent réduire l'utilisation des clés composées à max 2, mais cela obscurcit les relations et la signification des faits que vous stockez dans vos tables. (Exemple de fonctionID peut être et ID d'un nom de fonction ou un ID d'une fonction qui est effectuée dans certaines combinaisons de division/département - on ne sait pas ce qu'il est et ils ne sont pas interchangeables, comme la différence entre une instance et une classe).

Questions connexes