Modellazione di una struttura di database per più tipi di utenti e le loro informazioni di contatto


10

Sto progettando un database che memorizzerà utenti di vario tipo. Prevalentemente (ma non esclusivamente) saranno attori, registi e scrittori. Attualmente ci sono solo quattro tipi di utenti che sono rilevanti. Esiste una possibilità esterna che questo numero possa aumentare, ma la probabilità è bassa - e in tal caso sarebbe un numero molto piccolo.

Il piano è quello di avere un userstavolo responsabile praticamente solo per l'accesso al sito ( name, emaile passwordle colonne più uno o due altri come ad esempio se sono state approvate, e updated_at), e tavoli aggiuntivi per ciascuno dei rispettivi tipi di utenti che ogni hanno il proprio set unico di colonne. Solo gli attori, per esempio, avranno una rubrica sull'etnia, solo i registi avrebbero una rubrica bio e solo gli scrittori dovrebbero fornire la loro posizione. Tuttavia, poiché non ho gestito un database di questa complessità prima, mi chiedo come organizzare un paio di aspetti:

In primo luogo, gli utenti possono essere uno o più combinazioni dei tipi di cui sopra. Quindi capisco che avrei bisogno di qualcosa come (ad esempio) una director_usertabella con director_ide user_idcolonne. Sarebbe quindi sufficiente per poter filtrare tutti gli utenti per tipo di ruolo e così via?

In secondo luogo, la maggior parte degli utenti avrà la possibilità di un profilo twitter e un numero di telefono. E tutti gli attori dovranno includere almeno un URL per uno dei loro altri profili di attori online; attualmente ci sono tre che possono includere, ma questo numero può aumentare. Ho ragione nel supporre che una tabella separata per ciascuno dei possibili profili / metodi di contatto sia un modo ottimale per organizzare i dati?

Risposte:


14

Secondo la mia interpretazione della tua descrizione del contesto aziendale di interesse, hai a che fare con una struttura di sottotipo di sottotipo 1 in cui (a) attore , regista e scrittore sono sottotipi di entità di (b) persona , il loro sottotipo di entità e (c) detti sottotipi non si escludono a vicenda.

In questo modo, se sei interessato a costruire un database relazionale che rispecchi accuratamente uno scenario del genere, e quindi ti aspetti che funzioni come tale, i tuoi chiarimenti sui commenti che seguono sono abbastanza significativi rispetto ai punti precedenti, perché hanno implicazioni in entrambi (1) i livelli concettuali e (2) logici di rappresentazione del database in questione:

  • […] Tabelle aggiuntive per ciascuno dei rispettivi tipi di utenti che hanno ciascuno il proprio set univoco di colonne.

  • […] Ci sono solo quattro tipi di utenti che sono rilevanti. Esiste una possibilità esterna che questo numero possa aumentare, ma la probabilità è bassa - e in tal caso sarebbe un numero molto piccolo.

Descriverò tutti questi aspetti e molti altri fattori critici nelle sezioni seguenti.

Regole di business

Al fine di definire innanzitutto lo schema concettuale corrispondente, che può essere utilizzato come riferimento successivo in modo da poterlo adattare per assicurarsi che soddisfi i requisiti informativi esatti , ho formulato alcune regole di business di particolare importanza:

  • Una persona può svolgere ruoli da uno a due o tre (cioè da tutti a tutti) 2 . In altre parole, una persona può essere
    • un attore e
    • un direttore e
    • uno scrittore .
  • Una persona può accedere tramite UserProfile zero o uno .
  • Un attore fornisce uno o due o tre URL 3 .
  • Un attore è raggruppato per un'etnia .
  • Un Etnia gruppi zero-uno-o-molti attori .
  • Uno scrittore si basa in una posizione .
  • Una posizione è la base di zero-uno-o più scrittori .

Diagramma IDEF1X dell'esposizione

Quindi, ho creato il diagramma IDEF1X 4 mostrato nella Figura 1 , che raggruppa tutte le formulazioni sopra insieme ad altre regole che sembrano pertinenti:

Figura 1 - Diagramma IDEF1X per ruoli personali e dettagli di contatto nel cinema

Come dimostrato, il supertipo Person (i) ha una propria casella, (ii) possiede le proprietà o gli attributi che si applicano a tutti i sottotipi e (iii) presenta linee che lo collegano alle caselle di ogni sottotipo.

A sua volta, ogni sottotipo (a) appare nella sua casella dedicata e (b) detiene esclusivamente le proprietà applicabili. Il PRIMARY KEY del supertipo, PersonId , migra 5 nei sottotipi con i nomi dei ruoli 6 ActorId , DirectorId e WriterId rispettivamente.

Inoltre, ho evitato di associare Person con il tipo di entità UserProfile , che consente di separare tutte le loro implicazioni contestuali, associazioni o relazioni, ecc. La proprietà PersonId è migrata a UserProfile con il nome ruolo UserId .

Lo affermi nel corpo della domanda

E tutti gli attori dovranno includere almeno un URL per uno dei loro altri profili di attori online; attualmente ci sono tre che possono includere, ma questo numero può aumentare.

... quindi l' URL è un tipo di entità a sé stante ed è direttamente associato al sottotipo Actor in conformità con questa citazione.

E, nei commenti , lo specifichi

[...] un attore avrà un colpo alla testa (foto), mentre uno scrittore non [...]

... poi, tra le altre caratteristiche, ho incluso Headshot come proprietà del tipo di entità Attore .

Per quanto riguarda i tipi di entità Etnia e Ubicazione , ovviamente possono comportare organizzazioni più complesse (ad esempio, un Attore può appartenere a uno, due o più diversi gruppi etnici in proporzioni distinte e uno Scrittore può essere basato su un luogo che richiede la registrazione paese, regione amministrativa, contea, ecc.) ma sembra che le esigenze del tuo contesto aziendale siano coperte con successo con le strutture qui modellate.

Naturalmente, puoi apportare tutte le regolazioni necessarie.

Progettazione logica illustrativa SQL-DDL

Di conseguenza, sulla base del diagramma IDEF1X mostrato e descritto sopra, ho scritto il layout logico DDL che viene mostrato come segue (ho fornito note come commenti che spiegano alcune delle caratteristiche che reputo particolarmente importanti rispetto a tabelle, colonne e vincoli dichiarato):

-- You should determine which are the most fitting 
-- data types and sizes for all your table columns 
-- depending on your business context characteristics.

-- Also, you should make accurate tests to define the 
-- most convenient INDEX strategies based on the exact 
-- data manipulation tendencies of your business needs.

-- As one would expect, you are free to utilize 
-- your preferred (or required) naming conventions. 

CREATE TABLE Person ( -- Represents the supertype.
    PersonId       INT      NOT NULL,
    FirstName      CHAR(30) NOT NULL,
    LastName       CHAR(30) NOT NULL,
    BirthDate      DATE     NOT NULL,
    GenderCode     CHAR(3)  NOT NULL,
    TwitterProfile CHAR(30) NOT NULL,
    PhoneNumber    CHAR(30) NOT NULL,
    EmailAddress   CHAR(30) NOT NULL,  
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT Person_PK  PRIMARY KEY (PersonId),
    CONSTRAINT Person_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
        FirstName,
        LastName,
        GenderCode,
        BirthDate
    ),
    CONSTRAINT Person_AK2 UNIQUE (TwitterProfile), -- ALTERNATE KEY.
    CONSTRAINT Person_AK3 UNIQUE (EmailAddress)    -- ALTERNATE KEY.
);

CREATE TABLE Ethnicity ( -- Its rows will serve a “look-up” purpose.
    EthnicityId     INT      NOT NULL,
    Name            CHAR(30) NOT NULL,  
    Description     CHAR(30) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Ethnicity_PK PRIMARY KEY (EthnicityId),
    CONSTRAINT Ethnicity_AK UNIQUE      (Description)   
);

CREATE TABLE Actor ( -- Stands for one of the subtypes.
    ActorId         INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Headshot        CHAR(30) NOT NULL, -- May, e.g., contain a URL indicating the path where the photo file is actually stored. 
    EthnicityId     INT      NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Actor_PK            PRIMARY KEY (ActorId),
    CONSTRAINT ActorToPerson_PK    FOREIGN KEY (ActorId)
        REFERENCES Person (PersonId),
    CONSTRAINT ActorToEthnicity_PK FOREIGN KEY (EthnicityId)
        REFERENCES Ethnicity (EthnicityId)   
);

CREATE TABLE Director ( -- Denotes one of the subtypes
    DirectorId      INT       NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Bio             CHAR(120) NOT NULL,  
    Etcetera        CHAR(30)  NOT NULL,
    CreatedDateTime DATETIME  NOT NULL,
    -- 
    CONSTRAINT Director_PK         PRIMARY KEY (DirectorId),
    CONSTRAINT DirectorToPerson_PK FOREIGN KEY (DirectorId)
        REFERENCES Person (PersonId)   
);

CREATE TABLE Country (
    CountryCode     CHAR(2)  NOT NULL,
    Name            CHAR(30) NOT NULL,  
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Country_PK PRIMARY KEY (CountryCode),
    CONSTRAINT Country_AK UNIQUE      (Name)   
);

CREATE TABLE Location ( -- Its rows will serve a “look-up” purpose.
    CountryCode     CHAR(2)  NOT NULL,
    LocationCode    CHAR(3)  NOT NULL,
    Name            CHAR(30) NOT NULL,  
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Location_PK PRIMARY KEY (CountryCode, LocationCode),
    CONSTRAINT Location_AK UNIQUE      (CountryCode, Name)   
);

CREATE TABLE Writer ( -- Represents one of the subtypes.
    WriterId        INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    CountryCode     CHAR(2)  NOT NULL,
    LocationCode    CHAR(3)  NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT Writer_PK           PRIMARY KEY (WriterId),
    CONSTRAINT WriterToPerson_PK   FOREIGN KEY (WriterId)
        REFERENCES Person (PersonId),
    CONSTRAINT WriterToLocation_PK FOREIGN KEY (CountryCode, LocationCode)
        REFERENCES Location (CountryCode, LocationCode)  
);

CREATE TABLE UserProfile (
    UserId          INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    UserName        CHAR(30) NOT NULL,
    Etcetera        CHAR(30) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT UserProfile_PK PRIMARY KEY (UserId),
    CONSTRAINT UserProfile_AK UNIQUE      (UserName), -- ALTERNATE KEY.
    CONSTRAINT UserProfileToPerson_PK FOREIGN KEY (UserId)
        REFERENCES Person (PersonId)    
);

CREATE TABLE URL (
    ActorId       INT      NOT NULL,
    Address       CHAR(90) NOT NULL,
    Etcetera      CHAR(30) NOT NULL,
    AddedDateTime DATETIME NOT NULL,
    -- 
    CONSTRAINT URL_PK        PRIMARY KEY (ActorId, Address), -- Composite PRIMARY KEY.
    CONSTRAINT URLtoActor_FK FOREIGN KEY (ActorId)
        REFERENCES Actor (ActorId)
);

Pertanto, (1) ogni aspetto singolare del layout logico sopra riportato ha un significato molto preciso da (2) una caratteristica singolare dell'ambiente di business di interesse 7 — in accordo con lo spirito del quadro relazionale del Dr. Edgar Frank Codd -, perché:

  • Ogni tabella di base rappresenta un tipo di entità individuale.
  • Ogni colonna rappresenta una singola proprietà del rispettivo tipo di entità.
  • Un tipo di dati specifico è fissato per ogni colonna al fine di garantire che tutti i valori in esso contenuti appartengano a un insieme particolare e delimitato correttamente a, sia INT, DATETIME, CHAR, ecc. (E speriamo che MySQL integrerà finalmente DOMAIN supporto nella versione futura).
  • Più vincoli sono configurati (in modo dichiarativo) al fine di garantire che le asserzioni sotto forma di righe conservate in tutte le tabelle siano conformi alle regole di business determinate a livello concettuale.
  • Ogni riga ha lo scopo di trasmettere una semantica ben definita, ad esempio una Personriga viene letta

    La persona identificata da PersonId rviene chiamata da FirstName se LastName t, è nata il giorno della nascita u, ha il GenderCode v, i tweet sul profilo Twitter w, è raggiunta tramite PhoneNumber x, è contattata tramite EmailAddress yed è stata registrata su CreatedDateTimez .

Avere un layout come questo è decisamente favorevole, in quanto è possibile ricavare nuove tabelle (ad esempio, operazioni SELECT che raccolgono colonne DA più tabelle con l'aiuto della clausola JOIN) che - in successione - hanno anche un significato molto preciso (vedere la sezione intitolato "Visualizzazioni" di seguito).

Va detto che, con questa configurazione, (i) una riga che rappresenta un'istanza di sottotipo è identificata da (ii) lo stesso valore PRIMARY KEY che distingue la riga che indica l'occorrenza del supertipo complementare. Pertanto, è più che opportuno annotarlo

  • (a) collegare una colonna aggiuntiva per contenere surrogati generati dal sistema e assegnati al sistema da 8 a (b) le tabelle che rappresentano i sottotipi è (c) del tutto superflua .

Con questo progetto logico, se i nuovi sottotipi sono definiti rilevanti nel contesto aziendale, è necessario dichiarare una nuova tabella di base, ma ciò accade anche quando altri tipi di tipi di entità sono considerati significativi, quindi la situazione sarebbe, in infatti, ordinario.

Visualizzazioni

Per "recuperare", ad esempio, tutte le informazioni che corrispondono a un attore , regista o scrittore , è possibile dichiarare alcune visualizzazioni (ovvero tabelle derivate o espressibili ) in modo da poter SELEZIONARE direttamente da una singola risorsa senza dover scrivere il per quanto riguarda JOINs ogni volta; ad esempio, con la VISTA dichiarata di seguito, è possibile ottenere le informazioni "complete" sull'attore :

--
CREATE VIEW FullActor AS

    SELECT P.FirstName,
           P.Lastname,
           P.BirthDate,
           P.GenderCode,
           P.TwitterProfile,
           P.PhoneNumber,
           P.EmailAddress,
           A.Headshot,
           E.Name AS Ethnicity
         FROM Person P
         JOIN Actor A
           ON A.ActorId     = P.PersonId
         JOIN Ethnicity E
           ON E.EthnicityId = A.EthnicityId;
--

Naturalmente, è possibile seguire un approccio simile al fine di recuperare le informazioni "complete" su Director e Writer :

--
CREATE VIEW FullDirector AS

    SELECT P.FirstName,
           P.Lastname,
           P.BirthDate,
           P.GenderCode,
           P.TwitterProfile,
           P.PhoneNumber,
           P.EmailAddress,
           D.Bio,
           D.Etcetera
         FROM Person P
         JOIN Director D
           ON D.DirectorId = P.PersonId; 

--
CREATE VIEW FullWriter AS

    SELECT P.FirstName,
           P.Lastname,
           P.BirthDate,
           P.GenderCode,
           P.TwitterProfile,
           P.PhoneNumber,
           P.EmailAddress,
           L.Name AS Location,
           C.Name AS Country
         FROM Person P
         JOIN Writer W
           ON W.WriterId     = P.PersonId
         JOIN Country C
           ON C.CountryCode  = W.CountryCode
         JOIN Location L
           ON L.LocationCode = W.LocationCode;   
--

Ho pubblicato tutte le dichiarazioni DDL e le viste DML qui discusse in questo SQL Fiddle in esecuzione su MySQL 5.6 in modo da poterle vedere e testare "in azione".


Note finali

1 In alcune tecniche di modellazione concettuale, le associazioni supertipo-sottotipo sono definite relazioni superclasse-sottoclasse .

2 Anche se dici che in realtà esistono più ruoli che una persona può svolgere, ma i tre che hai rivelato sono abbastanza buoni da discutere dello scenario esponendo diverse importanti ramificazioni .

3 Ma, come hai notato, in futuro un attore potrebbe eventualmente fornire da uno a molti URL .

4 Integration Definition for Information Modeling ( IDEF1X ) è una tecnica di modellazione altamente raccomandabile che è stata stabilita come standard nel dicembre 1993 dal National Institute of Standards and Technology (NIST) degli Stati Uniti . Si basa su (a) le prime opere teoriche create dall'unico creatore del modello relazionale di dati, ovvero il Dr. EF Codd; su (b) il punto di vista entità-relazione , sviluppato dal Dr. PP Chen ; e anche su (c) la tecnica di progettazione del database logico, creata da Robert G. Brown.

5 Lo standard IDEF1X definisce la migrazione delle chiavi come "Il processo di modellizzazione del posizionamento della chiave primaria di un'entità padre o generica [cioè un supertipo] nella sua entità figlio o categoria [cioè un sottotipo] come chiave esterna".

6 In IDEF1X, un nome di ruolo è un'etichetta distintiva assegnata a un attributo FK per esprimere il significato che detiene nell'ambito del rispettivo tipo di entità.

7 Tranne, naturalmente, per le ipotetiche proprietà concettuali (e colonne logiche) Director.Etcetera e UserProfile.Etcetera , che sono semplicemente segnaposto che ho usato per esporre la possibilità di aggiungere più proprietà (e colonne) che si applicano al tipo di entità concettuale corrispondente (e tabella logica).

8 Ad esempio, aggiungendo una colonna aggiuntiva con l' attributo AUTO_INCREMENT a una tabella di un database "in esecuzione" su MySQL.


2

Dovresti dividerlo tra le tabelle in questo modo (mostrando solo le colonne necessarie per presentare il concetto, non necessariamente tutte le colonne):

Users
ID   Username   FirstName   LastName   PasswordHash ...
 1   'Joe1'      'Joe'      'Smith'
 2   'Freddy'    'Fred'     'Jones'

Roles
ID   RoleType ....
 1   'Writer'
 2   'Director'
 3   'Actor'

User_Roles
User_ID   Role_ID ...
1         1
1         2
2         2
2         3

Questo ti dà una tabella piena di utenti con tutte le varie colonne utente, una tabella di ruoli e una tabella di collegamento per connettere i due insieme.

Puoi vedere che Joe1 è sia uno scrittore che un regista dalle voci in User_Roles. E Freddy è sia un regista che un attore.

Ciò consente inoltre di aggiungere più ruoli in un secondo momento senza modificare il sistema. Basta inserire i record per Producer o Editor o qualunque altra cosa.

Quindi, per trovare tutti i nomi utente degli attori, hai un paio di scelte:

 Select Distinct Username
   from Users
  Where User_ID in (select User_ID from User_Roles where Role_ID = 3)

O se non conosci il numero role_ID, allora:

 Select Distinct Username
   from Users
  Where User_ID in (Select User_ID from User_Roles where Role_ID = 
                       (Select ID from Roles where RoleType = 'Actor')
                   )

Oppure puoi anche fare questo:

select u.Username, r.RoleType
  from Users u
 inner join User_Roles ur on ur.User_ID = u.ID
 inner join Roles r on r.ID = ur.Role_ID
 where r.RoleType = 'Actor'

(In questa versione, è possibile utilizzare anche Where r.Role_ID = 3per ottenere gli stessi risultati.)

Ma userei la prima query e la clausola WHERE che conoscevo. In un grande sistema, conoscere il Role_ID, in genere, verrà eseguito più velocemente del testo, poiché i dati numerici sono "più facili" e più efficienti per la maggior parte dei motori SQL per cui elaborare gli indici.

Per quanto riguarda i metodi di contatto o le foto o altro, li farei in modo simile:

Attributes
ID    MethodText    ...
1     'TwitterID'
2     'URL'
3     'CellPhone'
4     'Email'
5     'PictureLink'

Role_Attributes
Role_ID  Attribute_ID isRequired
3        5             1
3        4             1
3        3             0

User_Attributes
User_ID  Attribute_ID  AttributeData
1         4            'Joe@Example.com'
1         1            '@joe'
1         3            '555-555-5555'
1         5            'www.example.com/pics/myFace.png'

...e così via. Questi si collegherebbero allo stesso modo degli utenti ai ruoli.

Ciò dimostra che ogni ruolo ha da 0 a molti attributi, che possono essere facoltativi. Quindi ogni utente ha da 0 a molti attributi, con i dati per tali attributi.

Ciò consente di aggiungere nuovi attributi con il passare del tempo, senza riscrivere alcun codice; basta aggiornare le tabelle degli attributi e role_attributes in modo che corrispondano alle nuove regole. Inoltre, consente di condividere gli attributi tra i ruoli, senza immettere nuovamente gli stessi dati per ciascun utente. Se due ruoli richiedono foto, devono solo caricare 1 foto per soddisfare tale requisito.


Ah, penso che abbia senso in un certo senso ... ma non sono così chiaro su come - per esempio - elencherei tutti gli attori insieme, per esempio, i loro nomi utente (supponendo che i dati dell'attore siano archiviati in una tabella separata).
verismo

Vedi le mie modifiche; Ho aggiunto esempi di query.
CaM,

È immensamente utile, grazie. Penso che potrei non essere stato del tutto chiaro nella mia domanda, scusa. Avrei dovuto chiarire che le tabelle per ciascun tipo (attore, regista, ecc.) Avranno il loro set unico di attributi relativi solo a quel tipo di utente. Ad esempio, un attore avrà un colpo alla testa (foto), mentre uno scrittore no. Ci scusiamo ancora per non essere più esplicito al riguardo.
verismo

I metodi di contatto sembrano essere un'ottima soluzione.
verismo

1
Modificato questo per attribuire, per soddisfare i requisiti per le foto, ecc. Dovrebbe adattarsi meglio, ora.
CaM,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.