【问题标题】:MySQL - Return rows only if all the values in WHERE clause are presentMySQL - 仅当 WHERE 子句中的所有值都存在时才返回行
【发布时间】:2017-02-24 16:02:55
【问题描述】:

我有一个存储考试记录的数据库:tbl_exams 存储考试的 ID 和名称 - 只有 9 项考试,因此该表中只有 9 条记录,因为考试是固定的,不会更改。 tbl_exam_details 存储考试条目的所有详细信息,并包括来自 tbl_exams 的相应 id - 这有一个外键约束。我要做的是创建一个查询,仅当某个学生参加了所有 9 次考试并且 pass_or_fail 字段为“1”时才返回行 - 我使用 tinyint(1) 存储通过的 1,或者0 表示失败)。这实际上是为了检查是否所有 9 门考试都已通过。

这是我到目前为止所拥有的,但是即使学生只完成了一两次考试,它也会返回行:

SELECT tbl_exam_details.student_id, exam_name, exam_date, pass_or_fail FROM tbl_exam_details
INNER JOIN tbl_exams ON tbl_exams.exam_id = tbl_exam_details.exam_id
WHERE student_id = 1 AND pass_or_fail = 1
AND tbl_exam_details.exam_id IN (1, 2, 3, 4, 5, 6, 7, 8, 9)
ORDER BY exam_details_id

我需要的是查询只在所有 9 门考试都通过后才返回行。因此,如果学生通过了 8 次考试,则查询应返回 0 行。如果有人可以帮助我,将不胜感激。

【问题讨论】:

  • 您能否编辑您的问题并提供示例数据和所需的结果?
  • 您可以创建一个all_exams 列,该列将在修改表时自动更新。 all_exams = 1 如果设置了所有的exam_id,则为0。

标签: mysql sql


【解决方案1】:
SELECT ted.student_id, 
       exam_name, 
       exam_date, 
       pass_or_fail 
FROM tbl_exam_details ted
INNER JOIN tbl_exams 
   ON tbl_exams.exam_id = ted.exam_id
WHERE student_id = 1
  AND (SELECT COUNT(*)
       FROM tbl_exam_details ted2
       WHERE ted2.pass_or_fail = 1
         AND ted2.student_id = ted.student_id
      ) = 9  -- mean this student pass 9 exams
ORDER BY exam_details_id

【讨论】:

  • 为什么不WHERE tbl_exam_details.pass_or_fail = 1 AND tbl_exam_details.student_id = ted.student_id
  • @JohnHC 是的,我正在解决这个问题。谢谢
  • 将其标记为正确,因为它还会显示我需要的额外字段。
【解决方案2】:

这是你想要的吗?

SELECT ed.student_id
FROM tbl_exam_details ed
WHERE ed.student_id = 1 AND ed.pass_or_fail = 1 AND
      ed.exam_id IN (1, 2, 3, 4, 5, 6, 7, 8, 9)
GROUP BY ed.student_id
HAVING COUNT(*) = 9;  -- or maybe COUNT(DISTINCT exam_id) = 9

这将返回已通过 9 次考试的学生 ID。它不包含任何其他信息。

【讨论】:

  • 就是这样,谢谢!当它允许我时会接受正确的。出于好奇,您所说的“或者可能是 COUNT(DISTINCT Exam_id) = 9”是什么意思?
  • @sinesine 以防一个考试出现多次passed。但在这种情况下,你只能通过一次考试,所以应该不是问题。
  • 顺便说一句,您不需要and ed.exam_id IN (1, 2, 3, 4, 5, 6, 7, 8, 9),您已经说过只有 9 门考试,而您想要全部 9 门。所以 count(*) = 9 会处理好这个问题
【解决方案3】:

您可以通过 group_concat 获取完整列表...

select x1.*
from 
(
select t1.*, group_concat(distinct exam_id order by exam_id separator '|') as x_list
from tbl_exam_details t1
where pass_or_fail = 1
group by student_id
) x1
where x_list = '1|2|3|4|5|6|7|8|9'

【讨论】:

  • 您可能需要在concat上添加订单?
  • 这会产生错误:#1248 - Every derived table must have its own alias
猜你喜欢
  • 1970-01-01
  • 2021-11-16
  • 1970-01-01
  • 2011-08-31
  • 1970-01-01
相关资源
最近更新 更多