Melhor estrutura de tabelas para o problema

Boa noite Pessoal, estou com uma dúvida gigante sobre como estruturar o banco de dados da aplicação que estou desenvolvendo para um trabalho da faculdade.

Imaginem um sistema em que o usuário vai responder diversas perguntas com opções de respostas parametrizadas, como se fosse uma entrevista. Por exemplo:

Sexo : ()Masculino ()Feminino
Se acorda durante a noite para ir ao banheiro, qual é a frequência? ( ) 1 a 2 vezes ( ) 3 a 4 vezes ( ) 5 a 6 vezes ( ) mais de 6 vezes por noite

A estrutura que pensei foi uma tabela para Perguntas, uma tabela para Alternativas de respostas, pois não sei quantas respostas pode ter uma pergunta e nem quantas perguntas podem existir na pesquisa, uma tabela Questionário para saber quem respondeu as perguntas e vincular o ID do questionário a uma outra tabela de Respostas, para saber quais foram as respostas selecionadas.

Poderiam me dar alguma ideia melhor ou me dizer se o que pensei está bom?
Obrigado.

Também gostaria de saber a opinião de outras pessoas. Tive uma ideia assim:

CREATE TABLE `questao` (
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `conteudo` VARCHAR(255) NOT NULL
);

CREATE TABLE `alternativa` (
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `conteudo` VARCHAR(255) NOT NULL,
  `questao_id` INT UNSIGNED,
  FOREIGN KEY (`questao_id`) REFERENCES `questao`(`id`) ON DELETE CASCADE
);

CREATE TABLE `usuario` (
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `nome` VARCHAR(255) NOT NULL
);

CREATE TABLE `resposta` (
  `usuario_id` INT UNSIGNED,
  `alternativa_id` INT UNSIGNED,
  `extra` VARCHAR(255) DEFAULT NULL,
  FOREIGN KEY (`usuario_id`) REFERENCES `usuario`(`id`) ON DELETE CASCADE,
  FOREIGN KEY (`alternativa_id`) REFERENCES `alternativa`(`id`) ON DELETE CASCADE
);

No caso, a tabela resposta tem o campo extra pro caso de exigir que o usuário escreva a resposta, sabe?

Aí vc faria um SELECT assim:

SELECT
  usuario.nome,
  questao.conteudo AS questao,
  reposta.conteudo AS reposta,
  reposta.extra AS extra
FROM usuario
JOIN resposta ON resposta.usuario_id = usuario.id
JOIN alternativa ON alternativa.id = reposta.alternativa_id
JOIN questao ON questao.id = alternativa.questao_id;

Eu não pude testar muito e também não pensei em muitos possíveis cenários então realmente espero que outros respondam também.

Enquanto isso, o que vc acha?

Nossa foi quase o que pensei, mas tenho dúvida quanto a performance.
Vamos supor que eu tenha em torno de 80 questões, isso iria gerar 80 linhas de resposta para cada usuário.

Mas não consigo imaginar outra estrutura a não ser assim, o que tu acha da performance?
Sei que não preciso me preocupar com isso, por se tratar de um trabalho de faculdade, mas fiquei pensando kkkk

1 curtida

Que bom que está considerando performance desde já.

Se vc tem 80 questões, faz sentido retornar, pelo menos, 80 linhas.

Acho que o problema fica por conta de quando uma mesma questão pode ter mais de uma resposta. Imagina 80 questões de multipla escolha e em cada uma delas o usuario seleciona 2 alternativas, com o select que mostrei vc teria 160 linhas!

Dependendo da situação vc não vai conseguir fugir disso. Em outras, vc poderia remover algumas colunas do select e pedir pra trazer apenas as alternativas. E vc também poderia trazer tudo do banco e processar com sua linguagem de programação escolhida e retornar um JSON tipo assim:

[
  {
    "nome": "Fulano",
    "questoes": [
      {
        "conteudo": "Sexo",
        "respostas": [
          {
            "conteudo": "Masculino",
            "extra": null
          }
        ]
      }
    ]
  }
]

Ia ser legal ver o que os outros respondem. Quando ouço falar de performance em banco de dados, o assunto quase sempre está relacionado com a quantidade de selects que vc precisa fazer, eu ainda não ouvi falar se a quantidade de linhas é um problema. Mas eu também estou aprendendo.