Modelado de una estructura de base de datos para múltiples tipos de usuarios y su información de contacto


10

Estoy diseñando una base de datos que almacenará usuarios de diferentes tipos. Predominantemente (pero no exclusivamente) serán Actores, Directores y Escritores. Actualmente solo hay cuatro tipos de usuarios que son relevantes. Existe una posibilidad externa de que este número pueda aumentar, pero la probabilidad es baja, y en tal caso sería un número muy pequeño.

El plan es tener una userstabla responsables casi exclusivamente para iniciar sesión en el sitio ( name, emaily passwordcolumnas más uno o dos más, como si han sido aprobados, y updated_at), y las tablas adicionales para cada uno de los respectivos tipos de usuarios que cada tienen su propio conjunto único de columnas. Solo los actores, por ejemplo, tendrán una columna de etnicidad, solo los Directores tendrán una columna de biografía y solo los Escritores deberán proporcionar su ubicación. Sin embargo, como no he administrado una base de datos de esta complejidad antes, me pregunto cómo organizar un par de aspectos:

En primer lugar, los usuarios pueden ser cualquiera, o cualquier combinación, de los tipos anteriores. Así que entiendo que iba a necesitar algo así como (por ejemplo) una director_usermesa con director_idy user_idcolumnas. ¿Sería esto suficiente para poder filtrar a todos los usuarios por tipo de rol, etc.?

En segundo lugar, la mayoría de los usuarios tendrán la opción de un perfil de Twitter y un número de teléfono. Y todos los actores deberán incluir al menos una URL para cualquiera de sus otros perfiles de actores en línea; actualmente hay tres que pueden incluir, pero este número puede aumentar. ¿Estoy en lo cierto al suponer que una tabla separada para cada uno de los posibles perfiles / métodos de contacto es una forma óptima de organizar los datos?

Respuestas:


14

Según mi interpretación de su descripción del contexto comercial de interés, está tratando con una estructura de supertipo-subtipo 1 donde (a) Actor , Director y Escritor son subtipos de entidad de (b) Persona , su supertipo de entidad, y (c) dichos subtipos no son mutuamente excluyentes.

De esta manera, si está interesado en construir una base de datos relacional que refleje tal escenario con precisión, y por lo tanto espera que funcione como tal, sus siguientes aclaraciones de comentarios son bastante significativas con respecto a los puntos anteriores, porque tienen implicaciones en tanto (1) los niveles conceptuales y (2) lógicos de representación de la base de datos en cuestión:

  • [...] tablas adicionales para cada uno de los tipos de usuario respectivos, cada uno con su propio conjunto único de columnas.

  • [...] solo hay cuatro tipos de usuarios que son relevantes. Existe una posibilidad externa de que este número pueda aumentar, pero la probabilidad es baja, y en tal caso sería un número muy pequeño.

Explicaré todos esos aspectos y varios otros factores críticos en las siguientes secciones.

Reglas del negocio

Para definir primero el esquema conceptual correspondiente, que se puede utilizar como referencia posterior para que pueda adaptarlo y asegurarse de que cumple con los requisitos informativos exactos , he formulado algunas reglas comerciales que son de particular importancia:

  • Una persona puede llevar a cabo uno o dos o tres (es decir, uno a todos) Roles 2 . En otras palabras, una persona puede ser
    • un actor y
    • un director y
    • un escritor .
  • Una persona puede iniciar sesión a través de un perfil de usuario cero o uno .
  • Un actor proporciona una o dos o tres URL 3 .
  • Un actor se agrupa por una etnia .
  • Una etnia agrupa a los actores de cero uno o muchos .
  • Un escritor se basa en una ubicación .
  • Una ubicación es la base de cero-uno o más escritores .

Diagrama IDEF1X expositivo

Luego, creé el diagrama IDEF1X 4 que se muestra en la Figura 1 , que agrupa todas las formulaciones anteriores junto con otras reglas que parecen pertinentes:

Figura 1 - Diagrama IDEF1X para roles personales y detalles de contacto en cine

Como se demostró, el supertipo Persona (i) tiene su propio cuadro, (ii) posee las propiedades o atributos que se aplican a todos los subtipos y (iii) presenta líneas que lo conectan con los cuadros de cada subtipo.

A su vez, cada subtipo (a) aparece en su propio cuadro dedicado, y (b) posee exclusivamente sus propiedades aplicables. La CLAVE PRIMARIA del supertipo , PersonId , migra 5 a los subtipos con los nombres de roles 6 ActorId , DirectorId y WriterId respectivamente.

Además, evité asociar Person con el tipo de entidad UserProfile , lo que permite separar todas sus implicaciones contextuales, asociaciones o relaciones, etc. La propiedad PersonId ha migrado a UserProfile con el nombre de rol UserId .

Usted declara en el cuerpo de la pregunta que

Y todos los actores deberán incluir al menos una URL para cualquiera de sus otros perfiles de actores en línea; actualmente hay tres que pueden incluir, pero este número puede aumentar.

... por lo que URL es un tipo de entidad por derecho propio, y está directamente asociado con el subtipo Actor de acuerdo con esta cita.

Y, en los comentarios , especificas que

[...] un actor tendrá un tiro en la cabeza (foto), mientras que un escritor no [...]

... luego, entre otras características, incluí Headshot como una propiedad del tipo de entidad Actor .

En cuanto a los tipos de entidad de Etnia y Ubicación , por supuesto, pueden implicar organizaciones más complejas (por ejemplo, un Actor puede pertenecer a uno, dos o más grupos étnicos diferentes en proporciones distintas, y un Escritor puede estar basado en un lugar que requiere registro país, región administrativa, condado, etc.) pero parece que las necesidades de su contexto comercial se cubren con éxito con las estructuras aquí modeladas.

Naturalmente, puede hacer tantos ajustes como sea necesario.

Diseño lógico ilustrativo de SQL-DDL

En consecuencia, según el diagrama IDEF1X que se muestra y describe anteriormente, escribí el diseño DDL lógico que se muestra a continuación (he proporcionado notas como comentarios que explican algunas de las características que considero particularmente importantes con respecto a las tablas, columnas y restricciones declarado):

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

Por lo tanto, (1) cada aspecto singular del diseño lógico anterior tiene un significado muy preciso de (2) una característica singular del entorno empresarial de interés 7, de acuerdo con el espíritu del marco relacional del Dr. Edgar Frank Codd , porque:

  • Cada tabla base representa un tipo de entidad individual.
  • Cada columna representa una propiedad única del tipo de entidad respectivo.
  • Se fija un tipo de datos específico para cada columna para garantizar que todos los valores que contiene pertenecen a un conjunto particular y delimitado adecuadamente a, ya sea INT, DATETIME, CHAR, etc. (y esperemos que MySQL finalmente incorpore DOMAIN soporte en versión de futuro cercano).
  • Se configuran múltiples restricciones (declarativamente) para garantizar que las aserciones en forma de filas retenidas en todas las tablas cumplan con las reglas de negocio determinadas a nivel conceptual.
  • Cada fila está destinada a transmitir una semántica bien definida, por ejemplo, Personse lee una fila

    La persona identificada por PersonId rse llama por FirstName sy tLastName u, nació en BirthDate , tiene GenderCode v, tuitea en TwitterProfile w, se accede a través de PhoneNumber x, se contacta a través de EmailAddress yy se registra en CreatedDateTimez .

Tener un diseño como este es decididamente favorable, ya que puede derivar nuevas tablas (por ejemplo, operaciones SELECT que recopilan columnas de varias tablas con la ayuda de la cláusula JOIN) que, en sucesión, también tienen un significado muy preciso (consulte la sección titulado "Vistas" a continuación).

Es bueno mencionar que, con esta configuración, (i) una fila que representa una instancia de subtipo se identifica por (ii) el mismo valor de PRIMARY KEY que distingue la fila que indica la aparición de supertipo complementario. Por lo tanto, es más que oportuno notar que

  • (a) adjuntar una columna adicional para contener sustitutos 8 generados por el sistema y asignados al sistema (b) las tablas que representan los subtipos es (c) completamente superfluo .

Con este diseño lógico, si los nuevos subtipos se definen como relevantes en su contexto comercial, tendría que declarar una nueva tabla base, pero eso también ocurre cuando se considera que otros tipos de entidades son importantes, por lo que dicha situación sería, en hecho, ordinario.

Puntos de vista

Para "obtener", por ejemplo, toda la información que corresponde a un Actor , Director o Escritor , puede declarar algunas vistas (es decir, tablas derivadas o expresables ) para que pueda SELECCIONAR directamente desde un único recurso sin tener que escribir el acerca de las UNIONES cada vez; por ejemplo, con la VISTA declarada a continuación, puede obtener la información "completa" del actor :

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

Por supuesto, puede seguir un enfoque similar para recuperar la información "completa" del Director y del Escritor :

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

He publicado todas las declaraciones DDL y las vistas DML aquí discutidas en este SQL Fiddle que se ejecuta en MySQL 5.6 para que pueda verlas y probarlas "en acción".


Notas finales

1 En algunas técnicas de modelado conceptual, las asociaciones supertipo-subtipo se denominan relaciones superclase-subclase .

2 Aunque menciona que, de hecho, existen más Roles que una Persona puede realizar, pero los tres que reveló son lo suficientemente buenos como para discutir el escenario exponiendo varias ramificaciones importantes .

3 Pero, como notó, en el futuro un actor podría proporcionar URL de uno a muchos .

4 La definición de integración para el modelado de información ( IDEF1X ) es una técnica de modelado altamente recomendable que fue establecida como estándar en diciembre de 1993 por el Instituto Nacional de Estándares y Tecnología de los Estados Unidos (NIST). Se basa en (a) los primeros trabajos teóricos escritos por el único autor del modelo relacional de datos, es decir, el Dr. EF Codd; en (b) la vista entidad-relación , desarrollada por el Dr. PP Chen ; y también en (c) la Técnica de diseño de base de datos lógica, creada por Robert G. Brown.

5 El estándar IDEF1X define la migración de claves como "El proceso de modelado de colocar la clave primaria de una entidad primaria o genérica [es decir, un supertipo] en su entidad secundaria o de categoría [es decir, un subtipo] como una clave externa".

6 En IDEF1X, un nombre de rol es una etiqueta distintiva asignada a un atributo FK para expresar el significado que tiene dentro del alcance de su tipo de entidad respectivo.

7 Excepto, naturalmente, por las hipotéticas propiedades conceptuales (y columnas lógicas) Director.Etcetera y UserProfile.Etcetera , que son simplemente marcadores de posición que utilicé para exponer la posibilidad de agregar más propiedades (y columnas) que se aplican al tipo de entidad conceptual correspondiente (y tabla lógica).

8 Por ejemplo, agregar una columna adicional con el atributo AUTO_INCREMENT a una tabla de una base de datos "en ejecución" en MySQL.


2

Debería dividir esto en tablas como esta (solo mostrando las columnas necesarias para presentar el concepto, no necesariamente todas las columnas):

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

Esto le brinda una tabla llena de usuarios con todas las diferentes columnas de usuarios, una tabla de roles y una tabla de enlace para conectar los dos.

Puede ver que Joe1 es escritor y director por las entradas en User_Roles. Y Freddy es tanto director como actor.

Esto también le permite agregar más roles más adelante sin cambiar el sistema. Simplemente inserte registros para Productor o Editor o lo que sea más adelante.

Entonces, para encontrar todos los nombres de usuario de los actores, tiene un par de opciones:

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

O si no conoce el número de role_ID, entonces:

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

O también puedes hacer esto:

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'

(En esta versión, puede usar también use Where r.Role_ID = 3para obtener los mismos resultados).

Pero usaría la primera consulta y la cláusula WHERE que conocía. En un sistema grande, conocer el Role_ID generalmente se ejecutará más rápido que el texto, ya que los datos numéricos son "más fáciles" y más eficientes para la mayoría de los motores SQL para procesar los índices.

En cuanto a los métodos de contacto o fotos o lo que sea, los haría de manera similar:

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'

...y así. Estos se vincularían de la misma manera que los usuarios a los roles.

Esto muestra que cada rol tiene 0 a muchos atributos, que pueden ser opcionales. Entonces cada usuario tiene 0 a muchos atributos, con los datos para esos atributos.

Esto le permite agregar nuevos atributos a medida que pasa el tiempo, sin reescribir ningún código; solo actualice los atributos y las tablas role_attributes para que coincidan con sus nuevas reglas. También le permite compartir atributos entre roles, sin volver a ingresar los mismos datos para cada usuario. Si dos roles requieren imágenes, solo tienen que cargar 1 imagen para cumplir con ese requisito.


Ajá, creo que eso tiene sentido en un aspecto ... pero no tengo muy claro cómo, por ejemplo, enumeraría todos los actores junto con, por ejemplo, sus nombres de usuario (suponiendo que los datos del actor y estén almacenados en una mesa separada).
verismo

Mira mis ediciones; He agregado ejemplos de consultas.
CaM

Eso es inmensamente útil, gracias. Sin embargo, creo que no he sido completamente claro en mi pregunta, lo siento. Debería haber dejado más claro que las tablas para cada tipo (Actor, Director, etc.) tendrán su propio conjunto único de atributos relevantes solo para ese tipo de usuario. Por ejemplo, un actor tendrá un tiro en la cabeza (foto), mientras que un escritor no. Disculpas nuevamente por no ser más explícito sobre esto.
verismo

Los métodos de contacto parecen ser una gran solución.
verismo

1
Cambié eso a atributos, para cumplir con los requisitos para fotos, etc. Ahora debería ser mejor.
CaM
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.