4
respostas

Join com resultados diferentes.

Boa noite pessoal. Eu montei um esquema para tentar entender um pouco mais das relações das tabelas do sql e para tentar melhorar um pouco meu entendimento no curso. Não tenho como postar aqui o meu rascunho, mas talvez vocês possam me ajudar. Navegando pelas relações das tabelas para responder o exercício que indaga a respeito da média das notas por curso eu acabei chegando em duas querys diferentes que trazem resultados diferentes. Fiquei um tempo tentando entender, mas sem sucesso. Posto abaixo as duas e se alguém puder esclarece-las pra mim eu agradeço.

Caminho 1) Nota > Resposta > Aluno > Matricula > Curso

select c.nome, AVG(n.nota) from nota n
join resposta r on r.id = n.resposta_id
join aluno a on a.id = r.aluno_id
join matricula m on m.aluno_id = a.id
join curso c on c.id = m.curso_id
group by c.nome

Produz como resultado:

nome    (Nenhum nome de coluna)
C# e orientação a objetos    5.740740
Desenvolvimento mobile com Android    4.857142
Desenvolvimento web com VRaptor    6.250000
Scrum e métodos ágeis    5.777777
SQL e banco de dados    6.272727

Caminho 2) Nota > Resposta > Exercicio > Secao > Curso

select c.nome, AVG(n.nota) from nota n
join resposta r on r.id = n.resposta_id
join exercicio e on e.id = r.exercicio_id
join secao s on s.id = e.secao_id
join curso c on c.id = s.curso_id
group by c.nome

Produz:

nome    (Nenhum nome de coluna)
C# e orientação a objetos    4.857142
Desenvolvimento web com VRaptor    8.000000
Scrum e métodos ágeis    5.777777
SQL e banco de dados    6.100000

Percebi que uma das diferenças consiste no fato de executar um join entre as tabelas de Aluno e Resposta. O resultado desse join nos traz todas as respostas. Me parece que o sql não filtra, apesar de não cometer nenhuma falha. Mesmo assim, peço um norte a respeito de onde falha o meu entendimento e saber onde posso ler mais para sanar minha dúvida!

Desde já agradeço.

4 respostas

Bom dia, Sem saber o que esta nas tabelas fica difícil dizer o que exatamente está causando a diferença. Mas quando você usa Join (Inner Join) você exclui de seu resultado as linhas que não tem correspondentes na próxima tabela com quem você realiza o Join. Recomendo você dar uma lida sobre as diferenças entre Join, Left Join e Right Join. Faça um teste na sua consulta alterando o Join para "Left Join" e veja se resolve.

Eduardo

veja que o curso que retorna no caminho 1 e não no 2 é o Desenvolvimento mobile com Android. Esse curso não esta cadastrado na tabela de seção, que é uma tabela usada no seu caminho 2. Os demais cursos estão. No caminho 1, como você não utiliza a tabela seção, mais cursos podem retornar. Eu acrdito que todo curso deveria ter pelo menos uma seção mas o script não insere seções para todos os cursos.

Boa noite pessoal, agradeço a tentativa de esclarecimento por parte de vocês. Os dois comentários fazem sentido, mas a minha dúvida continua. Pelo que entendi até agora agora, o join relaciona as duas tabelas mas não filtra nada além da relação. Por isso algumas "inconsistências" ocorrem. Eu segui fazendo o curso e me deparei com outro exemplo.

Para calcular a média de notas por aluno por curso eu usei: 1) Nota > Resposta > Exercicio > Secao > Curso > Matricula > Aluno.

select a.nome,c.nome,AVG(n.nota) from nota n
join resposta r on r.id = n.resposta_id
join exercicio e on e.id = r.exercicio_id
join secao s on s.id = e.secao_id
join curso c on c.id = s.curso_id
join matricula m on m.curso_id = c.id
join aluno a on a.id = m.aluno_id
group by c.nome, a.nome

E o resultado obtido foi:

Alberto Santos    C# e orientação a objetos    4.857142
Alberto Santos    Scrum e métodos ágeis    5.777777
Frederico José    C# e orientação a objetos    4.857142
Frederico José    Desenvolvimento web com VRaptor    8.000000
Frederico José    SQL e banco de dados    6.100000
João da Silva    C# e orientação a objetos    4.857142
João da Silva    SQL e banco de dados    6.100000
Manoel Santos    Scrum e métodos ágeis    5.777777
Manoel Santos    SQL e banco de dados    6.100000
Paulo José    SQL e banco de dados    6.100000
Renata Alonso    C# e orientação a objetos    4.857142
Renata Ferreira    Desenvolvimento web com VRaptor    8.000000

Já o cálculo que me parece "certo", feito pelo instrutor foi: 2)

select a.nome, c.nome, avg(n.nota) from 
nota n
join resposta r on r.id = n.resposta_id
join exercicio e on e.id = r.exercicio_id
join secao s on s.id = e.secao_id
join curso c on c.id = s.curso_id
join aluno a on a.id = r.aluno_id
group by c.nome, a.nome

Que produziu como resposta:

Alberto Santos    Scrum e métodos ágeis    5.777777
Frederico José    Desenvolvimento web com VRaptor    8.000000
Frederico José    SQL e banco de dados    5.666666
João da Silva    SQL e banco de dados    6.285714
Renata Alonso    C# e orientação a objetos    4.857142

O que falho ainda em entender é por que essa lógica de "navegar" entre as relações acaba falhando. Não sei se fui claro o suficiente. Percebi que eu troquei os agrupamentos, mas a lógica de navegação permanece. No início da aula 3 existe um cálculo de "boletim" dos alunos em que novamente a relação entre aluno - matrícula - curso é ignorada, e aluno é ligado diretamente a resposta. Não saquei essa lógica de "navegar" entre as tabelas! Mais uma vez, desde já agradeço!

select c.nome, avg(n.nota) as média from curso c
join nota n on n.id = c.id
group by c.nome

Acabei chegando neste resultado, alguém pode por gentileza me explicar porque na minha lógica não inseri os outros Joins?