2012-04-01 25 views
18

Considerate questo caso in cui sto cercando di modellare un database per una società:Progettazione di database per una relazione ricorsiva

  • Entità: Employees, Managers, Departments.
  • Un Employee funziona solo in 1 Department mentre un Department può contenere molti Employees.
  • A Manager può gestire solo 1 Department e allo stesso modo un Department può avere solo 1 Manager.
  • A Manager supervisiona molti Employees, ma un Employee è supervisionato solo da uno Manager.

Ora ho 2 modi per modellare questo:

Prima soluzione:

Prenderò in considerazione che l'entità Manager eredita dalla Employee entità visto che io mantenere i dati unici per i Manager (es. Bonus & Status).

First Solution

  • Dal momento che il rapporto tra Department e Employee è 1:N poi metto il Department Id come chiave esterna nella tabella Employee per la relazione Works .

  • Dal momento che il rapporto tra Department e Manager è 1:1 poi metto il Department Id come chiave esterna nella tabella Manager per la relazione Manages .

Problema: Come posso rappresentare la relazione ricorsiva tra il Manager e Employee?


Seconda soluzione:

Prenderò in considerazione che l'entità Manager non è necessario in quanto altri Employees può anche avere un Bonus e Status.(In realtà ho aggiunto questi 2 attributi solo per vedere come modello in entrambi i casi) Second solution

  • Dal momento che il rapporto tra Department e Employee è 1:N allora metto il Department Id come chiave esterna nella Employee tabella per la relazione
  • Dal momento che il rapporto tra Employee e Manager è 1:N poi metto il Employee Id come chiave esterna nella tabella Employee per la relazione Supervises e lo chiamano Manager Id.

Problema: come posso rappresentare la relazione tra l'Manager e Department?


Domande:

  1. c'è qualche errori evidenti sia nel design così come sono?
  2. Come risolvere ciascun problema in entrambi i casi?
  3. C'è una soluzione migliore di questi due?

risposta

23

probabilmente sarei andare con qualcosa di simile:

enter image description here

Questo modello presenta le seguenti caratteristiche:

  • Manager "eredita" dipendente.
    • Per rappresentare un dipendente, inserire una riga singola in EMPLOYEE.
    • Per rappresentare un gestore, inserire una riga in EMPLOYEE e una riga in MANAGER.
  • Un reparto può avere più dipendenti.
  • Ogni reparto ha esattamente 1 manager e ogni manager gestisce 0 o 1 reparti.
  • Un supervisore può essere un impiegato ordinario o un manager.
  • dipartimenti non sono tenuti ad "abbinare":
    • Un supervisore può lavorare in reparto diverso da quello impiegato sorvegliato.
    • Un manager può gestire diversi reparti da dove lavora.
    • Se un supervisore è un manager, il/i dipartimento/i che gestisce, il/i dipartimento/i in cui lavora e il/i dipartimento/i dei suoi dipendenti supervisionati possono essere tutti diversi.

NOTA: Se il vostro DBMS non supporta vincoli anticipate, si vorrà fare il NULL in grado DEPARTMENT.MANAGER_ID, di rompere il ciclo che altrimenti si impedisce di inserire i nuovi dati.


Se i servizi sono tenuti a corrispondere, allora si sarebbe o impiegare una tecnica specifica-DBMS (ad esempio trigger o vincoli "speciali"), o "propagare" il DEPARTMENT_ID nella PK dei dipendenti. Questa propagazione è ciò che in definitiva consente l'abbinamento:

enter image description here

Da EMPLOYEE_ID deve essere univoco, non può rimanere nella chiave composta insieme al DEPARTMENT_ID. Quindi, facciamo la chiave alternativa e invece usiamo la surrogata EMPLOYEE_NO nel PK.

Questo modello impedisce di avere un manager che gestisce un reparto e lavora in un altro, o un supervisore che supervisiona i dipendenti di un reparto diverso.


Nel caso in cui non si ha familiarità con il simbolo ...

enter image description here

... denota una "categoria". In questo contesto, puoi semplicemente interpretarlo come una relazione "1 a 0 o 1" tra EMPLOYEE e MANAGER.

+0

+1 per lo sforzo con i diagrammi – Bohemian

+0

+1 per la risposta illustrativa :) Ma sei sicuro che questa parte sia corretta _ "Poiché EMPLOYEE_NO deve essere globalmente univoco, non può rimanere nella chiave composta insieme al DEPARTMENT_ID" _? Intendevi forse "EMPLOYEE_ID"? e cosa intendi esattamente con _ "Se i dipartimenti devono corrispondere" _? – Songo

+0

@Songo Ho fatto un refuso (dovrebbe essere l'ID non NO), corretto, grazie! –

0

La mia opinione:

Tabella persona dove si aggiungere informazioni sia per i dipendenti e dirigenti, i manager sono troppo umani, lo sai? :), e hai un campo managerId da collegare all'ID del manager.

reparto tabella con le informazioni di reparto

e, se il lavoratore può appartenere a più di un reparto, creare un'employee_department tavolo di relazionarsi loro. Se un dipendente può appartenere a un solo dipartimento e non è necessario disporre di ulteriori informazioni nella relazione, aggiungere un campo ID dipartimento nella tabella Impiegato.

+0

L'unico tavolo per conservarli tutti è come la mia seconda soluzione, giusto? In pratica, stai proponendo che la tabella Employee abbia la seguente struttura 'Employee (Employee Id, Employee Name, Manager Id, Department Id, Manager Department Id)' giusto? – Songo

+0

non è necessario un ID reparto responsabile, solo ID reparto perché se il dipendente è un manager, il suo reparto sarà archiviato nella colonna ID dipartimento – Diego

+0

Ma il 'Manager' di un' Dipartimento' potrebbe non essere il 'Manager' di il 'Dipendente'. Il 'Manager' per' Dipendente' è il suo diretto supervisore, non l'intero responsabile di reparto. Come risolvere questo? – Songo

0

penso che questa sia la soluzione migliore:

DB Design

un manager è un dipendente che gestisce un reparto. La relazione ricorsiva è possibile ottenere con il prossimo flusso:

dipendente ha un reparto Un reparto ha un dipendente come responsabile

Forse è a portata di mano per dare al tavolo dipendente una colonna EmployeeType per definire il ruolo.

+0

Il 'Manager' di un' Dipartimento' potrebbe non essere il 'Manager' del' Dipendente'. Il 'Manager' per' Dipendente' è il suo diretto supervisore, non l'intero responsabile di reparto. Come risolvere questo? – Songo

+0

Se capisco bene, allora immagino dando al dipendente una relazione con un dipendente che è un manager. Quindi la tabella dei dipendenti ottiene un campo ManagerID che si riferisce a un EmployeeID. – pascalvgemert

1

Senza entrare nei dettagli, vi assicuro che la soluzione Dipendente/Manager/Dipartimento è, a lungo termine, fonte di dispiacere (in un primo momento) quindi una vera PITA (in seguito) per i responsabili di mantenere il database e/o sviluppare la sua interfaccia. Quindi ti consiglio di attenersi alla tua seconda proposta.

Per quanto riguarda la relazione responsabile/reparto, ci sono principalmente due modi per rappresentare questa relazione.Entrambe le soluzioni ti autorizzano a mantenere la tua relazione ricorsiva "Gestisci il Dipendente" oltre a una relazione "Responsabile del Dipartimento" che puoi implementare come segue:

1 - primo/semplice modo: aggiungi un manager/id dipendente nel tuo tavolo di dipartimento. Questo campo è ovviamente una chiave esterna alla tabella dipendente

2 - secondo/soluzione più complessa: aggiungere una tabella "manager" con i seguenti campi:

Manager id (PK, surrogate) 
Department id (FK) 
Employee id (FK) 
beginningDate 
endingDate 

dove potrete memorizzare la cronologia gestione: chi, per quale dipartimento, da quando, fino a quando

In questo caso non dimenticare di aggiungere un po 'di logica (trigger o controllo sul lato client) per tradurre le tue regole di business come puoi avere un solo manager per uno specifico periodo e un reparto specifico, nessun dipartimento può stare più di ... senza un manager, ecc.

EDIT:

3 - una soluzione più ricca sarebbe una generalizzazione della mia seconda proposta, e vi permetterà di tenere traccia della carriera di tutti in azienda. Si può fare con un 'opere in' tavolo, come questo (come lo chiamiamo qui un tavolo 'posizione', farò la stessa terminologia qui:

Position id (PK, surrogate) 
Department id (FK) 
Employee id (FK) 
Position Level (FK) 
beginningDate 
endingDate 

Dove 'livello di posizione' porta a un'altra tabella che contiene le diverse posizioni che possono esistere in un dipartimento, una delle quali è ovviamente la posizione "manager"

Questa proposta è più vicina a ciò che viene utilizzato nel database delle risorse umane e software, e potrebbe non essere necessario un tale soluzione complessa, ma tieni presente che dividere gli esseri umani in più tavoli è SEMPRE un errore

MODIFICA: seguito il tuo commento ...

Per chiarire le cose, ti consigliamo di modificare i nomi dei campi. Mi piacerebbe proporre di avere i seguenti campi:

Tbl_Employee.id_EmployeeManager 

e

Tbl_Department.id_DepartmentManager 

fare questo, abbiamo (o qualsiasi sviluppatore) provvederemo immediatamente capire che id_EmployeeManager partecipa alla relazione ricorsiva tra le persone, mentre id_DepartmentManager partecipa alla relazione tra persone e dipartimento.

Torna alle vostre domande, e secondo me, non si deve creare il seguente link:

Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_EmployeeManager 

In questo modo, si sta che significa che qualcuno non può essere un responsabile di reparto a meno lui è già gestendo dipendenti. Che dire dei reparti con un singolo dipendente? Che dire delle persone nominate responsabili di un dipartimento appena creato, dove ancora nessun dipendente è allocato? Non funziona. Il link a destra dovrebbe essere:

Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_Employee 

Si potrebbe naturalmente aggiungere alcune regole di business dicendo per esempio che "un dipendente la gestione di un reparto non può che essere un manager" (id_Employee esiste da qualche parte come id_EmployeeManager) o "un impiegato che gestiscono una il dipartimento non può avere un manager (dove id_EmployeeManager per questo impiegato è nullo ...).Ma queste sono solo regole aziendali. Il tuo modello di dati è pulito per accettare tutte le regole fintanto che viene rispettata la regola di base, ovvero che un dipartimento è gestito da un dipendente!

+0

+1 per la grande spiegazione :) Ma ho poche domande. Nella tua prima (e più semplice) soluzione hai detto che dovrei aggiungere un campo ID responsabile/dipendente alla tabella del dipartimento. Dato che ho già aggiunto "Id del gestore" alla tabella "Dipendente" per la relazione ricorsiva, dovrei aggiungere un "Id del manager" alla tabella "Dipartimento" che fa riferimento all'ID "Responsabile" nella tabella "Dipendente" giusto? In questo modo solo un manager può gestire un reparto e nessun dipendente credo. – Songo

0

Che ne dici di attenersi al secondo design e avere una pseudo-relazione?

Suppongo che tu abbia una colonna department_id nell'entità Dipendente per collegare la relazione tra le entità Dipendente e Dipartimento. Se possiamo supporre che non ci sarà una gerarchia di manager (gestori di manager), possiamo applicare una pseudo-relazione tra le due tabelle in cui è Null (Manager_ID Null) rappresenta il Dipartimento che gestiscono.

Finché si documenta chiaramente questo, penso che sarebbe un approccio efficiente dal punto di vista dello spazio, poiché si avrebbe già una colonna FK (department_id) nell'entità Dipendente che fa riferimento all'entità Dipartimento.

Problemi correlati