sql >> Database >  >> RDS >> Oracle

Hoe ontwerp je een datamodel dat omgaat met de huidige medewerkers en voorspelde medewerkers?

Ik zie een aantal redenen waarom je hiervoor twee tabellen nodig hebt:

  • echte werknemers moeten een naam, een afdeling enz. hebben, terwijl voorspelde werknemers alleen deze kenmerken mogen hebben
  • er zullen verantwoordelijkheden zijn die alleen echte werknemers kunnen hebben, dus u wilt ze afzonderlijk kunnen raadplegen

Maar tegelijkertijd wilt u ervoor zorgen dat er geen botsing van ID's over de twee tabellen is, omdat (hopelijk) voorspelde werknemers daadwerkelijke werknemers zullen worden.

De manier om dit te doen is door een supertype/subtype structuur te implementeren. U hebt dus één tabel, WERKNEMERS die enkele primaire sleutels garandeert, en twee afhankelijke tabellen voor werkelijke en voorspelde werknemers. Het gebruik van de typekolom is cruciaal, omdat het ervoor zorgt dat een bepaalde medewerker slechts in één subtabel voorkomt.

create table employees
    ( emp_id number not null
      , emp_type varchar2(8) not null
      , constraint emp_pk primary key (emp_id)
      , constraint emp_uk unique (emp_id, emp_type)
      , constraint emp_type_ck check (emp_type in ('FORECAST', 'ACTUAL'));

create table actual_employees
    ( emp_id number not null
      , emp_type varchar2(8) not null
      , name varchar2(30) not null
      , deptno number(2,0) not null
      , sal number(7,2) not null
      , hiredate date not null
      , constraint actemp_pk primary key (emp_id)
      , constraint actemp_type_ck check (emp_type = 'ACTUAL')
      , constraint actemp_emp_fk foreign key (emp_id, emp_type)
                   references emp (emp_id, emp_type) 
                   deferrable initially deferred ;

create table forecast_employees
    ( emp_id number not null
      , emp_type varchar2(8) not null
      , name varchar2(30) 
      , deptno number(2,0) 
      , sal number(7,2) 
      , predicted_joining_date date
      , constraint foremp_pk primary key (emp_id)
      , constraint foremp_type_ck check (emp_type = 'FORECAST')
      , constraint foremp_emp_fk foreign key (emp_id, emp_type)
                   references emp (emp_id, emp_type) 
                   deferrable initially deferred ;

Dus de toetsen zien er misschien een beetje vreemd uit. De bovenliggende tabel heeft zowel een primaire sleutel als een samengestelde unieke sleutel. De primaire sleutel garandeert een enkele instantie van de EMP_ID. Met de unieke sleutel kunnen we externe sleutels bouwen op de onderliggende tabellen die verwijzen naar zowel de EMP_ID als de EMP_TYPE. Gecombineerd met de controlebeperkingen op het kind tDit komt omdat ze verwijzen naar de unieke sleutel in de bovenliggende tabel in plaats van naar de primaire sleutel. Deze regeling zorgt ervoor dat een werknemer in FORECAST_EMPLOYEES of ACTUAL_EMPLOYEES kan zijn, maar niet in beide.

De externe sleutels zijn uitstelbaar om de conversie van verwachte werknemers naar daadwerkelijke werknemers mogelijk te maken. Dit vereist drie activiteiten:

  1. het record van FORECAST_EMPLOYEES verwijderen
  2. een record invoegen in ACTUAL_EMPLOYEES
  3. het EMP_TYPE wijzigen (maar niet de EMP_ID) in EMPLOYEES.

Het synchroniseren van acties 2 en 3 is gemakkelijker met uitgestelde beperkingen.

Merk ook op dat andere beperkingen voor refererende sleutels die verwijzen naar WERKNEMERS de primaire sleutel moeten gebruiken in plaats van de unieke sleutel. Als de relatie om het type werknemer geeft, moet deze waarschijnlijk naar de onderliggende tabellen linken.

Welkom in de wereld van datamodellering. Het is één grote hoofdpijn. Omdat het moeilijk is om de rommelige realiteit in een schoon datamodel te passen :u hebt duidelijke vereisten nodig om het goed te doen, en inzicht in wat het belangrijkst is, zodat u verstandige compromissen kunt sluiten.

Ik heb een supertype/subtype-benadering voorgesteld op basis van uw andere vraag, en omdat het de beste manier lijkt om met twee sets gegevens om te gaan:echte werknemers en fictieve werknemers. Ik denk dat die twee groepen anders moeten worden behandeld. Ik zou er bijvoorbeeld op aandringen dat managers echte werknemers zijn. Dit is gemakkelijk te doen met een integriteitsbeperking tegen ACTUAL_EMPLOYEES en veel moeilijker te bereiken met een enkele tabel die beide typen werknemers bevat.

Zeker, het hebben van twee tabellen betekent mogelijk meer werk met betrekking tot het synchroniseren van hun structuren. En dan? Het is grotendeels triviaal, omdat het nauwelijks meer werk is om twee ALTER TABLE-instructies te schrijven dan één. Bovendien is het heel goed mogelijk dat de nieuwe kolom alleen van toepassing is op daadwerkelijke werknemers en geen betekenis heeft voor het voorspellen van werknemers (bijv. EARNED_COMMISSION, LAST_REVIEW_RATING). In dat licht maakt het hebben van aparte tabellen het datamodel nauwkeuriger.

Wat betreft het moeten dupliceren van afhankelijke tabellen, zoals Ollie opmerkt, is dat een misverstand. Tabellen die van toepassing zijn op alle werknemers, ongeacht hun realiteit, moeten verwijzen naar de tabel WERKNEMERS en niet naar de onderliggende tabel.

Ten slotte begrijp ik niet waarom het bijhouden van historische gegevens moeilijker is met twee tabellen dan voor één. De meeste journaalcodes zouden volledig uit de datadictionary moeten worden gegenereerd.

Er zijn drie tabellen:

  • EMPLOYEES - een hoofdtabel om unieke EMP_ID's te garanderen
  • ACTUAL_EMPLOYEES - een kindertafel voor mensen die voor uw bedrijf werken
  • FORECAST_EMPLOYEES - een kindertafel voor mensen die u voor uw bedrijf hoopt te werven

Houd er rekening mee dat ik aannames maak over uw bedrijfslogica op basis van de schaarse details die u heeft verstrekt.

Nu lijkt het mij dat mensen die nog niet voor uw bedrijf werken, geen aanverwante activiteiten mogen hebben. In dat scenario zou u één tabel hebben, EMPLOYEE_ACTIVITIES, die een onderliggend element is van ACTUAL_EMPLOYEES.

Maar misschien heb je wel echt activiteiten voor mensen die niet bestaan. Dus hier is een keuze:één tafel of twee? Het ontwerp met één tabel heeft EMPLOYEE_TASKS als een kind van de hoofdtabel EMPLOYEES. Het ontwerp met twee tabellen heeft ACTUAL_EMPLOYEE_TASKS en FORECAST_EMPLOYEE_TASKS als onderliggende items van respectievelijk de tabellen ACTUAL_EMPLOYEES en FORECAST_EMPLOYEES.

Welk ontwerp het juiste is, hangt af van de vraag of u regels moet handhaven met betrekking tot taaktoewijzing. Uw bedrijf kan bijvoorbeeld een regel hebben die stelt dat alleen echte mensen nieuw personeel kunnen aannemen. Het zou dus handig zijn om een ​​model te hebben waarmee alleen wervingstaken kunnen worden toegewezen aan ACTUAL_EMPLOYEES.

Oké, ik heb datumkolommen toegevoegd aan de twee tabellen. Hiermee kunt u het gewenste rapport uitvoeren.



  1. Linked Server Insert-Select Performance

  2. Ongebruikte unieke waarden op een SQL-tabel krijgen

  3. MySQL:vind snel rijen die geen overeenkomstige rij in een andere tabel hebben

  4. Verklaring verhogen