Suponha que eu tenha uma Tabela student
e uma Tabela exam
que rastreie todos os exames que um aluno fez, como faço para encontrar todos os alunos que passaram ou não fizeram nenhum exame semelhante a uma lista branca? Neste exemplo, isso significa os alunos 1 e 2.
PS: pass
sinalizador U
significa que o status é desconhecido, active
sinalizador N
significa que o exame foi removido, o restante dos sinalizadores é autoexplicativo.
Só para deixar bem claro, o caso de uso real é, na verdade assessments
, preciso descobrir as pessoas que não têm pending
avaliações para participar, para que possam prosseguir com o próximo conjunto de procedimentos. Outros precisariam terminar os itens pendentes.
+-------------+------+
| student_idn | name |
+-------------+------+
| 1 | Mark |
| 2 | Jack |
| 3 | Jane |
| 4 | Jill |
+-------------+------+
+----------+-------------+------+--------+
| exam_idn | student_idn | pass | active |
+----------+-------------+------+--------+
| 1 | 1 | Y | Y |
| 2 | 1 | Y | Y |
| 3 | 1 | Y | Y |
| 4 | 2 | Y | Y |
| 5 | 2 | N | N |
| 6 | 3 | Y | Y |
| 7 | 3 | Y | Y |
| 8 | 3 | Y | Y |
| 9 | 3 | N | Y |
| 10 | 4 | U | Y |
+----------+-------------+------+--------+
Eu vim com esta consulta abaixo, mas existe uma maneira melhor de fazer isso? Eu sinto que isso é O(n) ou O(nlogn) dependendo do índice etc. não tenho certeza (alguém sabe o melhor possível para isso), portanto, deve estar próximo do ideal?
SELECT
*
FROM student
WHERE NOT EXISTS (SELECT
*
FROM exam
WHERE exam.student_idn = student.student_idn
AND pass <> 'Y'
AND active = 'Y')
O problema que você descreve é conhecido como divisão relacional. Existem basicamente duas maneiras de abordá-lo:
Ou seja, transformar alunos que passaram em todas as provas para alunos onde não existe uma prova que o aluno não passou. Sua consulta na pergunta é um exemplo disso.
Essa transformação costuma ser chamada de
De Morgan's laws for quantifiers
. Veja por exemplo:https://philosophy.stackexchange.com/questions/28324/proving-de-morgans-laws-for-quantifiers
Alunos que passaram a mesma quantidade de testes que há testes. Algo como:
Estou respondendo de um celular, então não consigo ver a pergunta enquanto respondo, então os detalhes da minha resposta provavelmente estão errados de acordo com sua pergunta, mas espero que você tenha uma ideia.
Que tal agora:
O seguinte é menos dispendioso em desempenho:
Na verdade deveria ser assim, dessa forma não precisa juntar as duas tabelas: