Pergunta

Eu estou trabalhando em uma atualização para um banco de dados existente que foi projetado sem qualquer do código para implementar o projeto a ser considerada. Agora eu bater em uma parede de tijolos em termos de implementação do projeto de banco de dados no código. Estou certo se o seu problema um com o design do banco de dados ou se eu simplesmente não estou vendo a solução correta sobre como o que precisa ser feito.

A lógica básica estipula o seguinte:

  1. Os usuários acessam os treinamentos on-line por meio de assentos. Os usuários podem ter vários lugares.
  2. Os assentos são adquiridos por empresas e ter um relacionamento muitos-para-muitos com os produtos.
  3. Um produto tem um relacionamento muitos-para-muitos com os módulos.
  4. Um módulo tem um relacionamento muitos-para-muitos com lições.
  5. As lições são o acesso aos usuários finais para a sua formação.
  6. Para turvar as águas, por uma razão ou outra, alguns usuários têm vários lugares que contêm os mesmos produtos.
  7. Certificação ocorre em um por produto base, não em uma base por Seat.
  8. Os usuários têm um relacionamento muitos-para-muitos com lições que armazena seu status atual ou marcar para a lição.
  9. Os usuários certificar de um Produto quando completar todas as lições em todos os módulos do produto.
  10. Também é importante saber quando todas as lições para um módulo específico são completadas por um usuário.
  11. Alguns assentos será para recertificação o que significa que usuários que previamente certificados para um produto pode se inscrever e fazer um exame de recertificação.
  12. Devido o artigo 11, os usuários podem e terá vários registros de certificação.
  13. Editar: Quando um usuário conclui uma lição (pontuação melhor do que 80%), em seguida, o usuário tem (de acordo com a lógica de negócios atual) completou a lição para todos os produtos e todos os lugares que contêm a lição.

O problema que eu continuo correndo para com o design atual e a lógica de negócios como eu tenho mais ou menos descrito é que eu não consigo encontrar uma maneira de amarrar efetivamente se um usuário certificado para um determinado produto e assento vs quando eles não têm. Eu mantenho-me bater senões tentando estabelecer quais os produtos em que assentos foram certificadas para o utilizador e que não têm. Parte do problema é porque se eles estão atualmente registrados para múltiplas do mesmo produto em diferentes lugares, então eu tenho que contar o produto apenas uma vez.

Abaixo está uma cópia da parte do esquema que está envolvido. Todas as sugestões sobre como melhorar o design ou desenhar a associação em código seria apreciada. No caso é importante, este site é construído sobre a pilha LAMPP.

Você pode ver a parte relevante do esquema de banco de dados aqui: http://lpsoftware.com/problem_db_structure.png

Foi útil?

Solução

O que você está procurando relacional divisão Não implementado diretamente no SQL, mas isso pode ser feito. Pesquisa do Google para outros exemplos.

Outras dicas

Depois de um rápido olhar para o esquema Eu acho que uma das coisas que você pode fazer é criar um 'to_be_certified' mesa. Preenchê-lo com user_id, product_id e SEAT_ID quando um produto é atribuído a um assento (quando product_seat_rtab é preenchida).

Ao adicionar um registro à tabela certification_rtab, excluir o registro correspondente na tabela 'to_be_certified'. Isto lhe dará um fácil acesso a todos os produtos que são certificados por usuários e os que não são.

Para se livrar de product_ids duplicados, você pode agrupar por product_id.

Você precisa fazer alterações na tabela de lessonstatus_rtab:

CREATE TABLE lessonstatus_rtab (
  user_id    INT NOT NULL,
  seat_id    INT NOT NULL,
  lesson_id  INT NOT NULL REFERENCES lesson_rtab,
  accessdate TIMESTAMP,
  score      NUMERIC(5,2) NOT NULL DEFAULT 0,
  PRIMARY KEY (user_id, seat_id, lesson_id),
  FOREIGN KEY (user_id, seat_id) REFERENCES user_seat_rtab (user_id, seat_id)
);

Em seguida, você pode consultar para cada produto que um usuário tem um assento para, ele está certificado? Isso pressupõe que o número de lições que ele marcou, digamos, 50% ou mais é o mesmo que o número de aulas em todos os módulos do produto.

SELECT p.name, us.user_id, us.seat_id, COUNT(l.id) = COUNT(lu.lesson_id) AS is_certified
FROM user_seat_rtab AS us
 JOIN seat_rtab AS s ON (s.id = us.seat_id)
 JOIN product_seat_rtab AS ps ON (ps.seat_id = s.id)
 JOIN product_rtab AS p ON (p.id = ps.product_id)
 JOIN product_module_rtab AS pm ON (pm.product_id = p.id)
 JOIN module_rtab AS m ON (m.id = pm.module_id)
 JOIN module_lesson_rtab AS ml ON (ml.module_id = m.id)
 JOIN lesson_rtab AS l ON (l.id = ml.lesson_id)
 LEFT OUTER JOIN lessonstatus_rtab AS lu 
   ON (lu.lesson_id = l.id AND lu.user_id = us.user_id 
     AND lu.seat_id = us.seat_id AND lu.score > 0.50)
GROUP BY p.id, us.user_id, us.seat_id;

UPDATE:

Eu considerar esta questão e ter examinado se ele permitiria que as coisas funcionem melhor do que simplesmente remover a mesa de user_seat_rtab e, em seguida, use a tabela certification_rtab equivalente (provavelmente renomeado) para manter todas as informações sobre o status de sede de um usuário . Desta forma, existe uma relação direta estabelecida entre um usuário, o seu lugar, cada produto dentro do assento, e se o usuário tem certificado pelo Produto e lugar específico.

Assim, gostaria de aplicar as seguintes alterações ao esquema postado com a pergunta:

DROP TABLE user_seat_rtab;
RENAME TABLE certification_rtab TO something_different;

Uma alternativa para mais normalizar essa nova estrutura seria fazer algo como isto:

ALTER TABLE user_seat_rtab 
    DROP PRIMARY KEY;
    ADD COLUMN product_id int(10) unsigned NOT NULL;
    ADD CONSTRAINT pk_user_seat_product PRIMARY KEY (user_id, seat_id, product_id);
    ADD CONSTRAINT fk_product_user_seat FOREIGN KEY (product_id) REFERENCES product_rtab(id) ON DELETE RESTRICT;

Eu realmente não estou certo se isso iria resolver o problema ou se ele vai apenas mudar a natureza do problema um pouco e cria novos. Então, alguém tem alguma outras críticas ou sugestões?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top