MySQL查询:3个测试通过,1个失败
我正在尝试编写一个查询,将通过测试1到3但未通过测试4的学生拉出来 学生可以重考,因此可能会有失败记录,然后是一些考试的通过记录,例如下面的student_id=2 像这样的表格设置-MySQL查询:3个测试通过,1个失败,mysql,sql,tsql,Mysql,Sql,Tsql,我正在尝试编写一个查询,将通过测试1到3但未通过测试4的学生拉出来 学生可以重考,因此可能会有失败记录,然后是一些考试的通过记录,例如下面的student_id=2 像这样的表格设置- test_id | student_id | status | completed_on --------+------------+---------+------------ 1 | 1 | passed | 2018-03-24 2 | 1
test_id | student_id | status | completed_on
--------+------------+---------+------------
1 | 1 | passed | 2018-03-24
2 | 1 | passed | 2018-03-25
3 | 1 | passed | 2018-03-26
4 | 1 | failed | 2018-03-27
1 | 2 | failed | 2018-03-24
1 | 2 | passed | 2018-03-25
2 | 2 | passed | 2018-03-26
3 | 2 | passed | 2018-03-27
4 | 2 | failed | 2018-03-27
在这种情况下,查询应该同时提取student_id 1和2
我试过了,但显然没用-
select *
from table
where (test_id = 1 and status = 'passed')
and (test_id = 2 and status = 'passed')
and (test_id = 3 and status = 'passed')
and (test_id = 4 and status = 'failed')
我不是说这是快速或最有效的,但它会做的工作。确保您的表上有正确的索引
SELECT s1.student_id
FROM mytable s1
JOIN mytable s2 on s1.student_id=s2.student_id and s2.test_id=2 and s2.status='passed'
JOIN mytable s3 on s1.student_id=s3.student_id and s3.test_id=3 and s3.status='passed'
WHERE s1.test_id=1
AND s1.status='passed'
AND NOT EXISTS (
SELECT 1
FROM mytable s4
WHERE s4.student_id=s1.student_id
AND s4.test_id=4
AND s4.status='passed'
)
我不是说这是快速或最有效的,但它会做的工作。确保您的表上有正确的索引
SELECT s1.student_id
FROM mytable s1
JOIN mytable s2 on s1.student_id=s2.student_id and s2.test_id=2 and s2.status='passed'
JOIN mytable s3 on s1.student_id=s3.student_id and s3.test_id=3 and s3.status='passed'
WHERE s1.test_id=1
AND s1.status='passed'
AND NOT EXISTS (
SELECT 1
FROM mytable s4
WHERE s4.student_id=s1.student_id
AND s4.test_id=4
AND s4.status='passed'
)
这首先要确保每个学生、状态和考试ID都有不同的记录
然后,我们评估测试1、2、3、4中有多少通过,以及测试4中有多少失败。如果计数不是4,那么我们知道他们不是没有通过测试1-3,而是没有通过测试4,或者他们也通过了测试4。
这首先要确保每个学生、状态和考试ID都有不同的记录
然后,我们评估测试1、2、3、4中有多少通过,以及测试4中有多少失败。如果计数不是4,那么我们知道要么他们没有通过测试1-3,失败4,要么他们也通过了测试4。另一种方法:
select distinct t1.student_id
from mytable t1
inner join
-- students passed all the 3 tests
(select student_id from mytable where test_id in (1, 2, 3)
and status = 'passed' group by student_id having count(distinct test_id) = 3 ) t2
on t1.test_id = 4 and t1.status = 'failed' and t1.student_id = t2.student_id
where not exists
(select 1 from mytable where student_id = t1.student_id and
status = 'passed' and test_id = 4)
注:如果一名学生通过了一项测试(如测试1),但后来又参加了一次测试并失败,则该学生将被视为通过了测试。不确定这是否可以接受。另一种方法:
select distinct t1.student_id
from mytable t1
inner join
-- students passed all the 3 tests
(select student_id from mytable where test_id in (1, 2, 3)
and status = 'passed' group by student_id having count(distinct test_id) = 3 ) t2
on t1.test_id = 4 and t1.status = 'failed' and t1.student_id = t2.student_id
where not exists
(select 1 from mytable where student_id = t1.student_id and
status = 'passed' and test_id = 4)
注:如果一名学生通过了一项测试(如测试1),但后来又参加了一次测试并失败,则该学生将被视为通过了测试。不确定这是否可以接受。满足需求的一种方法是基本上制作一个透视表。无论您以何种方式对其进行切片,您都可能需要使用子查询,这里使用SUM函数和CASE语句,您可以确定每个学生通过测试的次数 然后,在外部WHERE子句中,您只能选择测试1到3的1个或多个“通过”结果以及测试4的0个“通过”结果所在的行 使用此技术,您还可以确定学生通过或未通过考试的次数。例如,您可以将CASE语句更改为“failed”,并在外部查询中返回测试列,以查看学生测试失败的次数。例如:
SELECT student_id, Test1Fails
FROM (SELECT student_id,
SUM(
CASE WHEN(test_id = 1 AND result = 'failed')
THEN 1
ELSE 0
END) AS "Test1Fails"
FROM TestResults
GROUP BY student_id) tr
您可以用来满足需求的一种方法是基本上创建一个透视表。无论您以何种方式对其进行切片,您都可能需要使用子查询,这里使用SUM函数和CASE语句,您可以确定每个学生通过测试的次数 然后,在外部WHERE子句中,您只能选择测试1到3的1个或多个“通过”结果以及测试4的0个“通过”结果所在的行 使用此技术,您还可以确定学生通过或未通过考试的次数。例如,您可以将CASE语句更改为“failed”,并在外部查询中返回测试列,以查看学生测试失败的次数。例如:
SELECT student_id, Test1Fails
FROM (SELECT student_id,
SUM(
CASE WHEN(test_id = 1 AND result = 'failed')
THEN 1
ELSE 0
END) AS "Test1Fails"
FROM TestResults
GROUP BY student_id) tr
假设一旦考试通过,就不会再尝试了,您可以获得每组考试id和学生id的最大值(已完成),然后只对这些行进行检查。@clinomaniac也就是说,接受的是一个日期;如果重拍发生在同一日期,则不能保证该日期的最大值是您想要的记录。理想情况下,该表也会有一个自动递增主键-然后您可以在groupsA记录中使用该主键的最大值test_ID=1和test_ID=2。因此,
和
需要是或
,然后您需要按学生ID对计数=4分组的唯一测试进行计数,但如果测试4进行了两次,第一次失败,然后通过。。。你会明白这一点,但你不想让它正确吗?不参加考试4算不算失败吗?因此,如果一个人没有测试记录,但他们通过了1-3次测试。。。你想让那个学生返回吗?假设一旦考试通过,就不再尝试了,你可以得到每组考试id和学生id的最大值(已完成),然后只对这些行进行检查。@clinomaniac也就是说,接受的是一个日期;如果重拍发生在同一日期,则不能保证该日期的最大值是您想要的记录。理想情况下,该表也会有一个自动递增主键-然后您可以在groupsA记录中使用该主键的最大值test_ID=1和test_ID=2。因此,和
需要是或
,然后您需要按学生ID对计数=4分组的唯一测试进行计数,但如果测试4进行了两次,第一次失败,然后通过。。。你会明白这一点,但你不想让它正确吗?不参加考试4算不算失败吗?因此,如果一个人没有测试记录,但他们通过了1-3次测试。。。你想让那个学生回来吗?我想你想让s3加入Critierion s3,而不是s2。似乎不这样做JOIN mytable s3 on s1.student\u id=s3.student\u id和s3.test\u id=3和s2.status='passed'
s/bJOIN mytable s3 on s1.student\u id=s3.student\u id=3和s3.status='passed'
我作弊并创建了一个rextester,并尝试了所有3个答案:P我自己没有找到它。我认为您希望s3加入到s3的Critieria中,而不是s2。似乎不这样做JOIN mytable s3 on s1.student\u id=s3.student\u id和s3.test\u id=3和s2.status='passed'
s/bJOIN mytable s3 on s1.student\u id=s3.student\u id=3和s3.status='passed'
我作弊并创建了一个rextester,并尝试了所有3个答案:P我自己没有找到它。好评论。成功之后的失败可能会产生不期望的结果。但是测试4有一个问题。如果学生在考试不及格后通过了怎么办。你明白了吗