I have the following table, which has the records of the answers to some academic quizzes:
Respostas
-SEMESTRE_ID (foreign key for semester of the quiz)
-PERGUNTA_ID (foreign key for the question of the quiz)
-DISCIPLINA_ID (foreign key for the subject being evaluated)
-DOCENTE_ID (foreign key for the teacher being evaluated)
-QUIZ_ID (each person answering a quiz has an unique quiz_id)
-TIPOAULA (type of class, doesn't matter for this context)
-DATA (date, doesn't matter for this context)
-ID (unique id of an answer)
-RESPOSTA (value of the answer, from 1 to 5)
So, a quizz of a given semester has multiples questions of different subjects, which can be evaluated by people (don't need to necessarily vote on all the questions).
The query I want to achieve is:
What's the id and acronym of the subjects that had at least a 5 in each one of the questions of the quiz of semester of id 21?
I've solved it using the counting strategy:
SELECT DISCIPLINA.DISCIPLINA_ID, SIGLA
FROM RESPOSTAS, DISCIPLINA
WHERE RESPOSTAS.DISCIPLINA_ID = DISCIPLINA.DISCIPLINA_ID AND SEMESTRE_ID = 21 AND RESPOSTA = 5
GROUP BY DISCIPLINA.DISCIPLINA_ID, SIGLA
HAVING COUNT(DISTINCT PERGUNTA_ID) = (SELECT COUNT(DISTINCT PERGUNTA_ID) FROM RESPOSTAS WHERE SEMESTRE_ID = 21);
But this is for an assignment and we're asked to also solve it by using the double negation strategy, which I can't seem to understand how to achieve the expected result.
This looks like a relational division query (if I'm not mistaken) and an example of the double negation that you're looking for is the query below. Basically it can be read as show me all subjects for which there exists no question not also in the set of question with a score of five or more
SELECT DISCIPLINA_ID, SIGLA
FROM XDISCIPLINA XD
WHERE NOT EXISTS ( -- there can not be any questions ...
SELECT 1 FROM XRESPOSTAS XR
WHERE SEMESTRE_ID = 21
AND NOT EXISTS ( -- that are not in the set of 5+
SELECT 1 FROM XRESPOSTAS
WHERE PERGUNTA_ID = XR.PERGUNTA_ID
AND SEMESTRE_ID = 21
AND RESPOSTA >= 5
AND XD.DISCIPLINA_ID = DISCIPLINA_ID
)
)
An good article on this is: Divided We Stand: The SQL of Relational Division by Joe Celko. It's well worth reading.
EDIT:
I think the query above was performing really bad due to a missing join. This version should perform a lot better:
SELECT DISCIPLINA_ID, SIGLA
FROM XDISCIPLINA XD
WHERE SEMESTRE_ID = 21
AND NOT EXISTS (
SELECT 1 FROM XRESPOSTAS XR
WHERE SEMESTRE_ID = 21 AND
XD.DISCIPLINA_ID = DISCIPLINA_ID AND
NOT EXISTS (
SELECT 1 FROM XRESPOSTAS
WHERE PERGUNTA_ID = XR.PERGUNTA_ID
AND SEMESTRE_ID = 21
AND RESPOSTA > 4
AND XD.DISCIPLINA_ID = DISCIPLINA_ID
)
)
Another way to achieve the same result that seem to perform a whole lot better:
SELECT DISCIPLINA_ID, SIGLA
FROM XDISCIPLINA XD
WHERE NOT EXISTS (
SELECT PERGUNTA_ID FROM XRESPOSTAS XR
WHERE SEMESTRE_ID = 21 AND XD.DISCIPLINA_ID = DISCIPLINA_ID
INTERSECT
SELECT PERGUNTA_ID FROM XRESPOSTAS XR
WHERE SEMESTRE_ID = 21 AND XD.DISCIPLINA_ID = DISCIPLINA_ID AND RESPOSTA < 5
)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.