Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Projetando relacionamentos em torno de uma estrutura de herança


Há uma pergunta semelhante aqui usando um supertipo de mídia e adicionando subtipos de CD, videocassete, DVD, etc.

Isso é escalável, pois ao criar, digamos, um subtipo BluRay, você cria a tabela para conter os dados específicos do BluRay e adiciona uma entrada à tabela MediaTypes. Nenhuma alteração necessária para dados ou códigos existentes - exceto, é claro, para adicionar o código que funcionará com dados BluRay.

No seu caso, Users seria a tabela de supertipos com Teachers e Students as tabelas 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 )
);

A composição da tabela Alunos seria semelhante à tabela Professores.

Como professores e alunos podem empregar outros professores e alunos, a tabela que contém essa relação se referiria à tabela Usuários.
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 )
);

Pelo que entendi, as Notificações são agrupadas por empregador:
create table Notifications(
    EmployerID    int not null
    NotificationDate date,
    NotificationData varchar( 500 ),
    -- other notification data...,
    constraint FK_NotificationsEmployer foreign key( EmployerID )
        references Users( ID )
);

As consultas devem ser bastante simples. Por exemplo, se um usuário quiser ver todas as notificações de seu(s) empregador(es):
select  e.EmployerID, n.NotificationDate, n.NotificationData
from    Employment  e
join    Notifications n
    on  n.EmployerID = e.EmployerID
where   e.EmployeeID = :UserID;

Este é um esboço inicial, é claro. Refinamentos são possíveis. Mas para seus pontos numerados:
  1. A tabela Emprego relaciona empregadores a empregados. A única verificação é fazer com que os empregadores de usuários não possam ser empregados, mas, caso contrário, qualquer usuário pode ser empregado e empregador.
  2. A tabela Users força cada usuário a ser um professor ('T') ou um aluno ('S'). Somente usuários definidos como 'T' podem ser colocados na tabela Professores e somente usuários definidos como 'S' podem ser colocados na tabela Alunos.
  3. A tabela Emprego se associa apenas à tabela Usuários, não às tabelas Professores e Alunos. Mas isso ocorre porque professores e alunos podem ser empregadores e funcionários, não por qualquer motivo de desempenho. Em geral, não se preocupe com o desempenho durante o projeto inicial. Sua principal preocupação neste momento é a integridade dos dados. Bancos de dados relacionais são muito bons com junções. Se um problema de desempenho deve surgir e corrigi-lo. Não reestruture seus dados para resolver problemas que ainda não existem e podem nunca existir.
  4. Bem, experimente e veja como funciona.