sql >> Base de Datos >  >> RDS >> Mysql

Diseño de relaciones en torno a una estructura de herencia

Hay una pregunta similar aquí usando un supertipo de medios y agregando subtipos de CD, VCR, DVD, etc.

Esto es escalable en el sentido de que, al crear, por ejemplo, un subtipo de BluRay, crea la tabla para contener los datos específicos de BluRay y agrega una entrada a la tabla MediaTypes. No se necesitan cambios para los datos o el código existente, excepto, por supuesto, para agregar el código que funcionará con los datos de BluRay.

En su caso, Usuarios sería la tabla de supertipos con Profesores y Alumnos las tablas de subtipos.

create table Users(
    ID      int not null auto_generating,
    Type    char( 1 ) check( Type in( 'T', 'S' )),
    -- other data common to all users,
    constraint PK_Users primary key( ID ),
    constraint UQ_UserType unique( ID, Type ),
    constraint FK_UserTypes foreign key( Type )
        references UserTypes( ID )
);
create table Teachers(
    TeacherID int not null,
    TeacherType char( 1 ) check( TeacherType = 'T' )),
    -- other data common to all teachers...,
    constraint PK_Teachers primary key( TeacherID ),
    constraint FK_TeacherUser foreign key( TeacherID, TeacherType )
        references Users( ID, Types )
);

La composición de la mesa de Estudiantes sería similar a la mesa de Profesores.

Dado que tanto los profesores como los alumnos pueden emplear a otros profesores y alumnos, la tabla que contiene esta relación se referiría a la tabla Usuarios.

create table Employment(
    EmployerID    int not null,
    EmployeeID    int not null,
    -- other data concerning the employment...,
    constraint CK_EmploymentDupes check( EmployerID <> EmployeeID ),
    constraint PK_Employment primary key( EmployerID, EmployeeID ),
    constraint FK_EmploymentEmployer foreign key( EmployerID )
        references Users( ID ),
    constraint FK_EmploymentEmployee foreign key( EmployeeID )
        references Users( ID )
);

Según tengo entendido, las Notificaciones están agrupadas por empleador:

create table Notifications(
    EmployerID    int not null
    NotificationDate date,
    NotificationData varchar( 500 ),
    -- other notification data...,
    constraint FK_NotificationsEmployer foreign key( EmployerID )
        references Users( ID )
);

Las consultas deben ser lo suficientemente simples. Por ejemplo, si un usuario quisiera ver todas las notificaciones de su(s) empleador(es):

select  e.EmployerID, n.NotificationDate, n.NotificationData
from    Employment  e
join    Notifications n
    on  n.EmployerID = e.EmployerID
where   e.EmployeeID = :UserID;

Este es un boceto inicial, por supuesto. Los refinamientos son posibles. Pero a sus puntos numerados:

  1. La tabla Empleo relaciona a los empleadores con los empleados. La única verificación es si para hacer que los empleadores de usuarios no puedan emplearse a sí mismos, pero de lo contrario, cualquier usuario puede ser tanto un empleado como un empleador.
  2. La tabla Usuarios obliga a cada usuario a ser profesor ('T') o estudiante ('S'). Solo los usuarios definidos como 'T' pueden colocarse en la tabla de Profesores y solo los usuarios definidos como 'S' pueden colocarse en la tabla de Estudiantes.
  3. La tabla Empleo se une solo a la tabla Usuarios, no a las tablas Profesores y Estudiantes. Pero esto se debe a que tanto los profesores como los estudiantes pueden ser tanto empleadores como empleados, no por ninguna razón de desempeño. En general, no se preocupe por el rendimiento durante el diseño inicial. Su principal preocupación en este momento es la integridad de los datos. Las bases de datos relacionales son muy buenas con las uniones. Si debería surgir un problema de rendimiento, luego solucionarlo. No reestructure sus datos para resolver problemas que aún no existen y que es posible que nunca existan.
  4. Bueno, pruébalo y verás cómo funciona.