Banco de Dados I — 2026.2

Aula 12
Laboratório de Consultas

Exercícios progressivos sobre o schema real do Alumnus

👨‍🏫 Prof. Gustavo Pinto 🏛️ UFPA 📅 11 de junho de 2026 🕣 7h30 – 9h10

O lab de hoje

Pegue as migrations em:

github.com/gustavopinto/alumnus/tree/main/backend/migrations

Rode uma após a outra, em ordem numérica (000_schema.sql, depois 001_…, 002_… e assim por diante). Cada migration evolui o schema a partir do estado anterior — pular ou trocar a ordem quebra o banco.

Tabelas que vamos usar

Atenção: nome, email e ativo vivem em users — não em researchers/professors. Quase toda consulta passa por users.

institutions

id, name, domain

professors

id
(só id — nome vem de users)

research_groups

id, name,
institution_id

researchers

id, status, matricula, curso, enrollment_date,
group_id, orientador_id

users

id, nome, email, role, ativo,
researcher_id, professor_id
CHECK: só um dos dois FKs

relationships

id, relation_type,
source_researcher_id,
target_researcher_id

notes

id, text, created_at,
user_id, created_by_id

reminders

id, text, due_date, done,
created_by_id, institution_id

deadlines

id, label, date,
abstract_date,
institution_id, created_by_id

deadline_interests

id,
deadline_id, user_id
UNIQUE (deadline_id, user_id)

milestones

id, type, title, date,
user_id

readings

id, title, url, status,
user_id

Setup do laboratório

① Abra o DB Fiddle

Selecione PostgreSQL no menu superior.

② Cole o schema

Cole o conteúdo de 000_schema.sql no painel Schema SQL e rode.

③ Popule o banco

Escreva seus próprios INSERTs — pelo menos 3 instituições, 3 grupos, 6 pesquisadores, 2 professores e algumas notas, lembretes e deadlines.

A qualidade dos dados que você inserir define se as consultas vão fazer sentido. Capriche.

10 consultas no Alumnus

1. Liste nome e email de todos os pesquisadores com status = 'doutorado', ordenados por nome. (dica: o nome está em users, ligado por users.researcher_id)

2. Todos os reminders ainda pendentes (done = FALSE), ordenados pela due_date crescente.

3. As 5 deadlines mais próximas que ainda não venceram (use CURRENT_DATE).

4. Para cada pesquisador ativo (users.ativo = TRUE): nome em caixa alta, o ano da enrollment_date e o domínio do e-mail.

5. Quantos pesquisadores existem por status?

6. Quais group_id têm mais de 1 pesquisador? (use HAVING)

7. Nome do pesquisador + nome do grupo de pesquisa a que pertence. (duplo JOIN: researchersusers e researchersresearch_groups)

8. Todos os pesquisadores + nome do orientador — incluindo os sem orientador. (o orientador também vem de users, mas via users.professor_id = researchers.orientador_id)

9. Para cada deadline: label e quantos usuários marcaram interesse.

10. Top 3 professores com mais pesquisadores ativos sob sua orientação.

Hora de pensar

Reflexões
sobre o schema

Você escreveu as consultas. Agora olhe para o schema e questione.

Reflexão 1 de 3

Um user é professor ou pesquisador?

A tabela users tem duas FKs: professor_id e researcher_id — só uma delas é preenchida por linha. Que problemas isso pode causar nas consultas e nos INSERTs? Como você redesenharia para evitar o NULL em uma das colunas? Vale criar duas tabelas separadas, ou herança, ou aceitar o trade-off?

Reflexão 2 de 3

Notas com duas referências a users

notes tem user_id (sobre quem é a nota) e created_by_id (quem escreveu). Em quais das 10 consultas isso atrapalhou? Como você renomearia essas colunas para deixar o papel de cada uma explícito? Esse padrão se repete em reminders e deadlines — você unificaria?

Reflexão 3 de 3

3 hops para chegar nas notas de um pesquisador

Para responder "quais pesquisadores nunca tiveram nota?" é preciso navegar researchers → users → notes. Se você pudesse mexer no schema, como encurtaria esse caminho? Vale colocar researcher_id direto em notes? O que se ganha em consulta e o que se perde em consistência?