Amigos,
Trabalho em uma Escola Pública e desemvolvi para mim mesmo um sistema para, entre outas, registar o rendimento dos alunos (notas e faltas). Para ler o Banco de Dados precisei fazer o sistema gerar a consulta, no começo era mais simples mas a coisa foi ficando cada vez mais cabeluda a medida que implementava novas funções.
Uso Delphi e FireBird e tenho as seguintes tabelas:
Alunos,
Matrículas,
Classes,
Bimestres,
Disciplinas,
Rendimentos /* notas e faltas, tem relacionamento com Disciplinas, Bimestres, e Matrículas /
e Classe_Disciplinas_Bimestres / Relacionamento entre as 3 */
Vejam só, para conseguir redimento completo de um aluno, (Boletim por ex.) Informo o ID do aluno, preciso retornar: O nome da classe, o nº Chamada, Nome do Aluno, o bimestre, notas e faltas de todas as disciplinas da classe e quantas aulas foram dadas na classe por todas as disciplinas.
Para vir tudo em uma só consulta o sistema gera vários SELF JOINS na tabela Rendimento de forma que para cada disciplina (geralmente 10) faço são 3 junções fora as outas tabelas que tb são mescladas por JOIN.
Eis um exemplo de consulta com apenas 2 disciplinas:
SELECT Y.CLA_NOME, X.MAT_NCHAMADA, Z.ALN_NOME, W.BIM_NOME, W.BIM_NO, W.BIM_ID,
/**/
disA.dis_nome_abreviado as dis0, A.REN_NOTA AS NOT0, A.REN_FALTAS AS FAL0, adA.cdb_aulasdadas as aldA,
disB.dis_nome_abreviado as dis1, B.REN_NOTA AS NOT1, B.REN_FALTAS AS FAL1, adB.cdb_aulasdadas as aldB
FROM (MATRICULAS X LEFT JOIN ALUNOS Z ON X.MAT_ALNID = Z.ALN_ID)
LEFT JOIN BIMESTRES W ON W.BIM_ANOID = 2011
LEFT JOIN CLASSES Y ON Y.CLA_ID = X.MAT_CLAID
LEFT JOIN RENDIMENTO A ON X.MAT_ID = A.REN_MATID AND A.REN_DISID = 1 AND W.BIM_ID = A.REN_BIMID left join disciplinas disA on disA.dis_id = 1 left join CLASSE_DIS_BIM adA on adA.cdb_claid = x.mat_claid and adA.cdb_disid = A.REN_DISID and adA.cdb_bimid = a.ren_bimid
LEFT JOIN RENDIMENTO B ON X.MAT_ID = B.REN_MATID AND B.REN_DISID = 2 AND W.BIM_ID = B.REN_BIMID left join disciplinas disB on disB.dis_id = 2 left join CLASSE_DIS_BIM adB on adB.cdb_claid = x.mat_claid and adB.cdb_disid = B.REN_DISID and adb.cdb_bimid = b.ren_bimid
/**/
WHERE X.MAT_ALNID = 1366
ORDER BY W.BIM_NO
As linhas entre /**/ são replicadas conforme a quantidade de disciplinas.
Quero saber dos mais experientes quais os problemas com um código tão longo, se tantos joins é algo normal ou se compromente o DB de alguma forma, alem de compartilhar com todos a experiência.