我有下表,其中包含一些学术测验答案的记录:
Respostas
-SEMESTRE_ID(测验学期的外键)
-PERGUNTA_ID(测验问题的外键)
-DISCIPLINA_ID(正在评估的主题的外键)
-DOCENTE_ID(正在评估的教师的外键)
-QUIZ_ID(每个回答测验的人都有一个独特的quiz_id)
-TIPOAULA(类的类型,对于此上下文无关紧要)
-DATA(日期,对于此上下文无关紧要)
-ID(答案的唯一ID)
-RESPOSTA(答案的值,从1到5)
因此,一个学期的一个问题是不同科目的问题,可以由人们评估(不需要对所有问题进行投票)。
我想要实现的查询是:
在id 21的学期测验中,每个问题至少有5个的主题的id和首字母缩写是什么?
我用计数策略解决了这个问题:
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);
但这是一项任务,我们也要求通过使用双重否定策略来解决它,我似乎无法理解如何达到预期结果。
答案 0 :(得分:3)
这看起来像是一个关系除法查询(如果我没有记错的话),你正在寻找的双重否定的一个例子就是下面的查询。基本上它可以被解读为向我显示所有主题,在问题集中不存在任何问题,分数为5或更多
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
)
)
关于此的一篇好文章是:Joe Celko的Divided We Stand: The SQL of Relational Division。这非常值得一读。
编辑:
我认为由于缺少连接,上面的查询执行得非常糟糕。这个版本的表现要好得多:
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
)
)
实现相同结果的另一种方法似乎表现得更好:
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
)