我试图编写一个查询,这将导致已经通过测试1到3且未通过测试4的学生。
学生可以重新参加测试,因此可能会有失败的记录,然后是一些测试的传递记录,例如下面的student_id = 2就是这种情况。
表格设置如下 -
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')
答案 0 :(得分:2)
SELECT count(Z.Test_ID), Z.student_ID
FROM (SELECT distinct student_ID, test_ID, Status
FROM table) Z
WHERE (Z.Status = 'Passed' and Z.test_ID in (1,2,3,4))
OR (Z.status = 'Failed' and Z.test_ID = 4)
GROUP BY Z.Student_ID
HAVING count(Z.Test_ID) = 4;
首先确保我们只为每个学生,状态和test_ID提供不同的记录。 (派生表Z)
然后我们评估测试1,2,3,4中存在多少次传递,并且测试4存在失败。如果计数不是4,那么我们知道他们没有通过测试1- 3并且失败4或者他们也通过了测试4。
答案 1 :(得分:1)
我没有声称这是快速或最有效的,但它会完成这项工作。确保你的桌子上有正确的索引,
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'
)
答案 2 :(得分:0)
另一种方法:
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)
PS。如果学生通过考试(例如考试1)但后来再次考试并失败,则该学生将被视为通过考试。不确定这是否可以接受。
答案 3 :(得分:0)
您可以使用一种方法来满足您的要求,基本上是制作数据透视表。无论你如何切片,你都可能需要使用子查询,这里使用SUM函数和CASE语句,你可以确定每个学生通过测试的次数。
然后,在你的外部WHERE子句中,你只能选择你有1个或更多个传递的行。测试1到3的结果,0'通过'测试结果4。
SELECT student_id
FROM (SELECT student_id,
SUM(
CASE WHEN(test_id = 1 AND result = 'passed')
THEN 1
ELSE 0
END) AS "Test1",
SUM(
CASE WHEN(test_id = 2 AND result = 'passed')
THEN 1
ELSE 0
END) AS "Test2",
SUM(
CASE WHEN(test_id = 3 AND result = 'passed')
THEN 1
ELSE 0
END) AS "Test3",
SUM(
CASE WHEN(test_id = 4 AND result = 'passed')
THEN 1
ELSE 0
END) AS "Test4"
FROM TestResults
GROUP BY student_id) tr
WHERE Test1 > 0 AND Test2 > 0 AND Test3 > 0 AND Test4 = 0
使用此技术,您还可以确定学生通过或未通过考试的次数。例如,您可以将CASE语句更改为“失败”。并返回外部查询中的测试列,以查看学生未通过测试的次数。例如:
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