Solucionado (ver solução)
Solucionado
(ver solução)
9
respostas

devolver os alunos com as respectivas quantidades de matriculas y respostas

Se uso esta query me devolve um valor errado. Porque?


select a.nome, count(m.id), count(r.id) from resposta r
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 a.nome
9 respostas

Olá Janile,

pode ser que por conta do produto cartesiano que ocorre entre as tabelas quando fazemos um join ele pode esta contando alguma matrícula ou resposta mais de uma vez no count. Veja se adicionando um distinct dentro da cláusula resolve o problema.

count(distinct m.id), count(distinct r.id)

Lucas, resolve o problema. Mas ainda nao entendi porque na query que te especifiquei as duas colunas traz valores iguais, porque tenho que adicionar o distinct

Na sua base tem algum aluno matriculado 2 vezes no mesmo curso?

O jeito mais fácil de encontrar quem é o causador do problema é tirando o group by a.nome e os count, deixando no select a.nome, m.id, r.id. Ai você consegue ver exatamente como ele juntou as tabelas e quem está duplicando resultado.

Quando faco o que vc me diz, existem varios registros repetidos. 10 registros de Paulo José, no curso sql, com o mesmo id de matricula para cada linha. De todo jeito, quando peco que me devolva qtde de matriculas de paulo jose devolve só uma e nao 10.

Este curso de sql que apareceu 10 vezes para o Paulo José possui 10 exercícios? Essa seria a razão de ele repetir a informação 10 vezes, pois nos joins vc junta as tabelas de seção, exercício e resposta também.

Entao qual seria a query correta usando joins?

Na verdade está correto desse jeito, isso faz parte do comportamento do join mesmo de fazer um produto cartesiano. Nesta consulta específica como você precisa recuperar tanto a quantidade de matriculas quanto a quantidade de respostas, as matrículas vão acabar repetindo mesmo. Ai que entra o uso do distinct para dizer na query que você quer contar na verdade matrículas de ids diferentes.

Desculpa. Mas ainda nao consigo entender porque ele ta repetindo o id da matricula. Nem porque conta essa repeticao. Se realmente quando quero saber quantas matriculas tem por cada aluno:

select a.nome, count(m.id) from aluno a 
join matricula m on m.aluno_id = a.id
group by a.nome

e me devolve, por exemplo que paulo jose so tem uma matricula:

Alberto Santos    2
Frederico José    3
João da Silva        2
Manoel Santos    2
Paula Soares        1
Paulo José        1
Renata Alonso    2
Renata Ferreira    1

E se depois executo a query para saber a qtde de matriculas por aluno e respostas por aluno me da diferente:

select a.nome, count(m.id), count(r.id) from resposta r
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 a.nome

o resultado que me da:

nome            (No column name)    (No column name)
Alberto Santos    16                        16
Frederico José    18                        18
João da Silva        17                        17
Manoel Santos    19                        19
Paulo José        10                        10
Renata Alonso    7                        7
Renata Ferreira    1                        1
solução!

A sacada na verdade é que ele está repetindo a matrícula pela quantidade de respostas de cada exercício. Uma query que vai te ajudar a ver é essa aqui que imprime o id do exercicio e da resposta:

select a.nome, m.id, e.id, r.id from resposta r
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

Note que de fato vão ter vários registros que terão o mesmo par nome e id de matrícula, mas o que vai mudar neles é o id do exercício e das respostas. E quando fazemos o group by pelo nome do aluno e fazemos simplesmente o count(m.id) ele não está contando quantas matrículas de ids diferentes tem, mas sim o total de m.id que vai ser igual a essa quantidade de exercícios diferentes que tem no curso.

Por exemplo, vamos supor que as suas tabelas estão assim:

Aluno
id    nome
1    João

Matricula
id    aluno_id    curso_id
1    1            7

Curso
id    nome
7    sql

Secao
id    curso_id
10    7

Exercicio
id    secao_id
20    10
21    10
22    10

Resposta
id    exercicio_id
30    20
31    21
32    22

A query lá de cima daria este resultado:

a.nome    m.id    e.id    r.id
João        1        20    30
João        1        21    31
João        1        22    32

E se eu simplesmente fizer um group by em a.nome e count(m.id), ele mostraria que João e 3, porque de fato tem 3 linhas com ids de matrículas.

Agr se eu fizer count(distinct m.id) ai sim vai dar apenas 1, pois só tem 1 id aparecendo na coluna inteira para o João.