Modélisation d'une structure de base de données pour plusieurs types d'utilisateurs et leurs coordonnées

10

Je conçois une base de données qui stockera des utilisateurs de types différents. Ils seront principalement (mais pas exclusivement) des acteurs, réalisateurs et scénaristes. Actuellement, seuls quatre types d'utilisateurs sont pertinents. Il y a une chance extérieure que ce nombre augmente, mais la probabilité est faible - et dans ce cas, ce serait par un très petit nombre.

Le plan consiste à avoir une userstable responsable à peu près uniquement de la connexion au site ( name, emailet des passwordcolonnes plus une ou deux autres, par exemple, si elles ont été approuvées et mises à jour_à), et des tables supplémentaires pour chacun des types d'utilisateurs respectifs que chacun ont leur propre ensemble unique de colonnes. Seuls les acteurs, par exemple, auront une colonne sur l'origine ethnique, seuls les réalisateurs auront une colonne sur la bio et seuls les scénaristes devront fournir leur emplacement. Cependant, comme je n'ai jamais géré de base de données de cette complexité auparavant, je me demande comment organiser quelques aspects:

Premièrement, les utilisateurs peuvent être n'importe lequel, ou n'importe quelle combinaison, des types ci-dessus. Je comprends donc que j'aurais besoin de quelque chose comme (par exemple) une director_usertable avec director_idet des user_idcolonnes. Cela suffirait-il alors pour pouvoir filtrer tous les utilisateurs par type de rôle, etc.?

Deuxièmement, la plupart des utilisateurs auront l'option d'un profil Twitter et d'un numéro de téléphone. Et tous les acteurs devront inclure au moins une URL pour l'un de leurs autres profils d'acteurs en ligne; actuellement, ils peuvent en inclure trois, mais ce nombre peut augmenter. Ai-je raison de supposer qu'un tableau séparé pour chacun des profils / méthodes de contact possibles est un moyen optimal d'organiser les données?

vérisme
la source

Réponses:

14

Selon mon interprétation de votre description du contexte commercial d'intérêt, vous avez affaire à une structure de supertype-sous-type 1 où (a) acteur , réalisateur et écrivain sont des sous-types d'entité de (b) personne , leur supertype d'entité, et (c) lesdits sous-types ne s'excluent pas mutuellement.

De cette façon, si vous êtes intéressé par la construction d'une base de données relationnelle qui reflète exactement un tel scénario - et que vous vous attendez donc à ce qu'il fonctionne comme tel -, les clarifications de vos commentaires suivantes sont assez importantes par rapport aux points précédents, car elles ont des implications sur à la fois (1) les niveaux conceptuels et (2) logiques de représentation de la base de données en question:

  • […] Tableaux supplémentaires pour chacun des types d'utilisateurs respectifs qui ont chacun leur propre ensemble unique de colonnes.

  • […] Il n'y a que quatre types d'utilisateurs qui sont pertinents. Il y a une chance extérieure que ce nombre augmente, mais la probabilité est faible - et dans ce cas, ce serait par un très petit nombre.

Je développerai tous ces aspects et plusieurs autres facteurs critiques dans les sections ci-dessous.

Règles métier

Afin de définir d'abord le schéma conceptuel correspondant - qui peut être utilisé comme référence ultérieure afin que vous puissiez l'adapter pour vous assurer qu'il répond aux exigences d'information exactes - , j'ai formulé quelques règles commerciales qui sont d'une importance particulière:

  • Une personne peut remplir un ou deux ou trois (c'est-à-dire un à tous) rôles 2 . En d'autres termes, une personne peut être
    • un acteur et
    • un directeur et
    • un écrivain .
  • Une personne peut se connecter via zéro ou un profil utilisateur .
  • Un acteur fournit une ou deux ou trois URL 3 .
  • Un acteur est groupé par une ethnie .
  • Une ethnie regroupe zéro ou un ou plusieurs acteurs .
  • Un écrivain est basé dans un seul endroit .
  • Un emplacement est la base de zéro un ou plusieurs écrivains .

Diagramme expositoire IDEF1X

Ensuite, j'ai créé le diagramme IDEF1X 4 illustré à la figure 1 , qui regroupe toutes les formulations ci-dessus ainsi que d'autres règles qui semblent pertinentes:

Figure 1 - Diagramme IDEF1X pour les rôles des personnes et les coordonnées au cinéma

Comme démontré, le supertype Personne (i) a sa propre boîte, (ii) possède les propriétés ou les attributs qui s'appliquent à tous les sous-types, et (iii) présente des lignes qui le connectent aux boîtes de chaque sous-type.

À son tour, chaque sous-type (a) apparaît dans sa propre boîte dédiée, et (b) détient exclusivement ses propriétés applicables. La CLÉ PRIMAIRE du supertype, PersonId , migre 5 vers les sous-types avec les noms de rôle 6 ActorId , DirectorId et WriterId respectivement.

J'ai également évité de coupler Person avec le type d'entité UserProfile , ce qui permet de séparer toutes leurs implications contextuelles, associations ou relations, etc. La propriété PersonId a migré vers UserProfile avec le nom de rôle UserId .

Vous déclarez dans le corps de la question que

Et tous les acteurs devront inclure au moins une URL pour l'un de leurs autres profils d'acteurs en ligne; actuellement, ils peuvent en inclure trois, mais ce nombre peut augmenter.

… Donc l' URL est un type d'entité à part entière, et est directement associée au sous-type Acteur conformément à cette citation.

Et, dans les commentaires , vous spécifiez que

[…] Un acteur aura un headshot (photo), alors qu'un écrivain n'aura pas […]

… Puis, entre autres fonctionnalités, j'ai inclus Headshot en tant que propriété du type d'entité Acteur .

Quant aux types d'entité Ethnicité et Lieu , ils peuvent bien sûr impliquer des organisations plus complexes (par exemple, un acteur peut appartenir à un, deux ou plusieurs groupes ethniques différents dans des proportions distinctes, et un écrivain peut être basé sur un lieu qui nécessite un enregistrement pays, région administrative, comté, etc.) mais il semble que les besoins de votre contexte commercial soient couverts avec succès avec les structures modélisées ici.

Naturellement, vous pouvez effectuer autant d'ajustements que nécessaire.

Conception logique illustrative SQL-DDL

Par conséquent, sur la base du diagramme IDEF1X montré et décrit ci-dessus, j'ai écrit la disposition DDL logique qui est montrée comme suit (j'ai fourni des notes sous forme de commentaires qui expliquent certaines des caractéristiques que j'estime particulièrement importantes en ce qui concerne les tableaux, les colonnes et les contraintes déclaré):

-- 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)
);

Par conséquent, (1) chaque aspect singulier de la disposition logique ci-dessus porte une signification très précise à partir de (2) une caractéristique singulière de l'environnement commercial d'intérêt 7 - en accord avec l'esprit du cadre relationnel par le Dr Edgar Frank Codd -, parce que:

  • Chaque table de base représente un type d'entité individuel.
  • Chaque colonne représente une seule propriété du type d'entité respectif.
  • Un type de données spécifique est fixé pour chaque colonne afin de garantir que toutes les valeurs qu'elle contient appartiennent à un ensemble particulier et correctement délimité a, que ce soit INT, DATETIME, CHAR, etc. (et espérons que MySQL incorporera enfin DOMAIN support dans une version proche).
  • De multiples contraintes sont configurées (de manière déclarative) afin de garantir que les assertions sous forme de lignes conservées dans toutes les tables respectent les règles métier déterminées au niveau conceptuel.
  • Chaque ligne est destinée à transmettre une sémantique bien définie, par exemple, une Personligne est lue

    La personne identifiée par PersonId rest appelée par le prénom set le nom de famille t, est née le BirthDate u, a le GenderCode v, les tweets sur le TwitterProfile w, est accessible via PhoneNumber x, est contactée via le EmailAddress yet a été enregistrée sur CreatedDateTimez .

Avoir une mise en page comme celle-ci est décidément favorable, car vous pouvez dériver de nouvelles tables (par exemple, des opérations SELECT qui rassemblent des colonnes FROM plusieurs tables à l'aide de la clause JOIN) qui - successivement - ont également une signification très précise (voir la section intitulé «Vues» ci-dessous).

Il convient de mentionner que, avec cette configuration, (i) une ligne représentant une instance de sous-type est identifiée par (ii) la même valeur PRIMARY KEY qui distingue la ligne indiquant l'occurrence de supertype complémentaire. Il est donc plus que opportun de noter que

  • (a) attacher une colonne supplémentaire pour contenir les substituts générés et attribués par le système 8 à (b) les tableaux représentant les sous-types est (c) entièrement superflu .

Avec cette conception logique, si de nouveaux sous-types sont définis comme pertinents dans votre contexte commercial, vous devrez déclarer une nouvelle table de base, mais cela se produit également lorsque d'autres types de types d'entités sont jugés importants, de sorte que ladite situation serait, dans fait, ordinaire.

Vues

Afin de «récupérer», par exemple, toutes les informations qui correspondent à un acteur , un réalisateur ou un écrivain , vous pouvez déclarer certaines vues (c'est-à-dire des tables dérivées ou exprimables ) afin de pouvoir sélectionner directement à partir d'une seule ressource sans avoir à écrire le concernant JOINs à chaque fois; Par exemple, avec la VUE déclarée ci-dessous, vous pouvez obtenir les informations d' acteur «complètes» :

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

Bien sûr, vous pouvez suivre une approche similaire afin de récupérer les informations "complètes" du réalisateur et du scénariste :

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

J'ai posté toutes les instructions DDL et les vues DML ici discutées dans ce SQL Fiddle fonctionnant sur MySQL 5.6 afin que vous puissiez les voir et les tester «en action».


Notes de fin

1 Dans certaines techniques de modélisation conceptuelle, les associations supertype-sous-type sont appelées relations superclasse-sous-classe .

2 Bien que vous mentionniez qu'il existe en fait plus de rôles qu'une personne peut jouer, mais les trois que vous avez révélés sont assez bons pour discuter du scénario exposant plusieurs ramifications importantes .

3 Mais, comme vous l'avez noté, à l'avenir, un acteur pourrait éventuellement fournir des URL un à plusieurs .

4 La définition d'intégration pour la modélisation de l'information ( IDEF1X ) est une technique de modélisation hautement recommandable qui a été établie comme norme en décembre 1993 par le National Institute of Standards and Technology (NIST) des États-Unis . Il est basé sur (a) les premiers travaux théoriques rédigés par le seul auteur du modèle relationnel de données, c'est-à-dire le Dr EF Codd; sur (b) la vue de l' entité-relation , développée par Dr. PP Chen ; et également sur (c) la technique de conception de bases de données logiques, créée par Robert G. Brown.

5 La norme IDEF1X définit la migration de clé comme «le processus de modélisation consistant à placer la clé primaire d'une entité parent ou générique [c'est-à-dire, un super-type] dans son entité enfant ou catégorie [c'est-à-dire un sous-type] comme clé étrangère».

6 Dans IDEF1X, un nom de rôle est une étiquette distinctive attribuée à un attribut FK afin d'exprimer la signification qu'il détient dans le cadre de son type d'entité respectif.

7 Sauf, naturellement, pour les propriétés conceptuelles hypothétiques (et les colonnes logiques) Director.Etcetera et UserProfile.Etcetera , qui ne sont que des espaces réservés que j'ai utilisés pour exposer la possibilité d'ajouter plus de propriétés (et colonnes) qui s'appliquent au type d'entité conceptuel correspondant (et tableau logique).

8 Par exemple, ajouter une colonne supplémentaire avec l' attribut AUTO_INCREMENT à une table d'une base de données «en cours d'exécution» sur MySQL.

MDCCL
la source
2

Vous devez le diviser en plusieurs tableaux comme celui-ci (en affichant uniquement les colonnes nécessaires pour présenter le concept, pas nécessairement toutes les colonnes):

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

Cela vous donne une table pleine d'utilisateurs avec toutes les différentes colonnes d'utilisateurs, une table de rôles et une table de liaison pour connecter les deux ensemble.

Vous pouvez voir que Joe1 est à la fois scénariste et réalisateur par les entrées dans User_Roles. Et Freddy est à la fois réalisateur et acteur.

Cela vous permet également d'ajouter plus de rôles ultérieurement sans modifier le système. Insérez simplement des enregistrements pour le producteur ou l'éditeur ou quoi que ce soit sur la ligne.

Donc, pour trouver tous les noms d'utilisateur des acteurs, vous avez deux choix:

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

Ou si vous ne connaissez pas le numéro de role_ID, alors:

 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')
                   )

Ou vous pouvez également le faire:

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'

(Dans cette version, vous pouvez également utiliser Where r.Role_ID = 3pour obtenir les mêmes résultats.)

Mais j'utiliserais la 1ère requête et la clause WHERE que je connaissais. Dans un grand système, connaître le Role_ID s'exécute généralement plus rapidement que le texte, car les données numériques sont "plus faciles" et plus efficaces pour la plupart des moteurs SQL pour traiter les index.

Quant aux méthodes de contact ou aux photos ou autre, je les ferais de la même manière:

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            '[email protected]'
1         1            '@joe'
1         3            '555-555-5555'
1         5            'www.example.com/pics/myFace.png'

...etc. Ceux-ci seraient liés de la même manière que les utilisateurs aux rôles.

Cela montre que chaque rôle a de 0 à de nombreux attributs, qui peuvent être facultatifs. Ensuite, chaque utilisateur a 0 à plusieurs attributs, avec les données de ces attributs.

Cela vous permet d'ajouter de nouveaux attributs au fil du temps, sans réécrire de code; mettez simplement à jour les tables d'attributs et de role_attributes pour qu'elles correspondent à vos nouvelles règles. Il vous permet également de partager des attributs entre les rôles, sans ressaisir les mêmes données pour chaque utilisateur. Si deux rôles nécessitent des photos, ils n'ont qu'à télécharger 1 photo pour remplir cette exigence.

Came
la source
Aha, je pense que cela a du sens sur un point ... mais je ne sais pas trop comment - par exemple - je listerais tous les acteurs avec, disons, leurs noms d'utilisateur (en supposant que les données de l'acteur-y sont stockées dans un tableau séparé).
verism
Voir mes modifications; J'ai ajouté des exemples de requêtes.
CaM
C'est extrêmement utile, merci. Je pense que je n'ai peut-être pas été complètement clair dans ma question - désolé. J'aurais dû indiquer plus clairement que les tables de chaque type (acteur, directeur, etc.) auront leur propre ensemble d'attributs unique pertinent uniquement pour ce type d'utilisateur. Par exemple, un acteur aura un headshot (photo), contrairement à un écrivain. Toutes mes excuses pour ne pas être plus explicite à ce sujet.
verism
Les méthodes de contact semblent être une excellente solution.
verism
1
Changé pour les attributs, pour répondre aux exigences pour les photos, etc. Devrait être mieux adapté, maintenant.
CaM