[英]Tricky SQL query involving consecutive values
I need to perform a relatively easy to explain but (given my somewhat limited skills) hard to write SQL query. 我需要执行相对容易解释的操作,但是(鉴于我的技能有限)很难编写SQL查询。
Assume we have a table similar to this one: 假设我们有一张与此表类似的表:
exam_no | name | surname | result | date
---------+------+---------+--------+------------
1 | John | Doe | PASS | 2012-01-01
1 | Ryan | Smith | FAIL | 2012-01-02 <--
1 | Ann | Evans | PASS | 2012-01-03
1 | Mary | Lee | FAIL | 2012-01-04
... | ... | ... | ... | ...
2 | John | Doe | FAIL | 2012-02-01 <--
2 | Ryan | Smith | FAIL | 2012-02-02
2 | Ann | Evans | FAIL | 2012-02-03
2 | Mary | Lee | PASS | 2012-02-04
... | ... | ... | ... | ...
3 | John | Doe | FAIL | 2012-03-01
3 | Ryan | Smith | FAIL | 2012-03-02
3 | Ann | Evans | PASS | 2012-03-03
3 | Mary | Lee | FAIL | 2012-03-04 <--
Note that exam_no
and date
aren't necessarily related as one might expect from the kind of example I chose. 请注意,
exam_no
和date
不一定像我选择的示例中所期望的那样相关。
Now, the query that I need to do is as follows: 现在,我需要执行的查询如下:
exam_no
= 3) find all the students that have failed ( John Doe
, Ryan Smith
and Mary Lee
). exam_no
= 3)中查找所有失败的学生( John Doe
, Ryan Smith
和Mary Lee
)。 The resulting table should be something like this: 结果表应该是这样的:
name | surname | date_since_failing
------+---------+--------------------
John | Doe | 2012-02-01
Ryan | Smith | 2012-01-02
Mary | Lee | 2012-03-04
How can I perform such a query? 如何执行这样的查询?
Thank you for your time. 感谢您的时间。
You can take advantage of the fact that if someone passed the most recent exam, then they have not failed any exams since their most recent pass: therefore the problem reduces to finding the first exam failed since the most recent pass: 您可以利用以下事实:如果某人通过了最近的考试,那么自从最近通过考试以来,他们还没有通过任何考试:因此,问题可以归结为找到自最近通过考试以来的第一次考试失败:
SELECT name, surname, MIN(date) date_since_fail
FROM results NATURAL LEFT JOIN (
SELECT name, surname, MAX(date) lastpass
FROM results
WHERE result = 'PASS'
GROUP BY name, surname
) t
WHERE result = 'FAIL' AND date > IFNULL(lastpass,0)
GROUP BY name, surname
I should use a subquery that fetch last passed exam, somthing like: 我应该使用可以获取最近通过的考试的子查询,例如:
SET @query_exam_no = 3;
SELECT
name,
surname,
MIN(IF(date > last_passed_exam, date, NULL)) AS date_failing_since
FROM
exam_results
LEFT JOIN (
SELECT
name,
surname,
MAX(date) AS last_passed_exam
FROM exam_results
WHERE result = 'PASS'
GROUP BY name, surname
) AS last_passed_exams USING (name, surname)
HAVING
MAX(IF(exam_no = @query_exam_no, result, NULL)) = 'FAIL'
GROUP BY name, surname
This is enough: 这就够了:
select t.name,
t.surname,
t.date as 'date_since_failing'
from tablename t
inner join
(
select name,
surname,
max(exam_no) as exam_no
from tablename
group by name, surname
having min(result) = 'FAIL'
) aux on t.name = aux.name and t.surname = aux.surname and t.exam_no = aux.exam_no
The condition you are asking for is good for nothing you can do it without it. 您所要求的条件无济于事,没有它您将无能为力。 Here is the working example.
这是工作示例。
select
e.name,
e.sur_name,
min(e.date) as `LastFailed`
from exams as e
where e.result = 'Fail'
group by e.name
order by e.name
This produces this result 这产生了这个结果
name sur_name LastFailed
Ann Evans 2012-02-03
John Doe 2012-02-01
Mary Lee 2012-01-04
Ryan Smith 2012-01-02
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.