MYSQL满足条件时获取值

4xy9mtcn  于 2022-12-17  发布在  Mysql
关注(0)|答案(2)|浏览(142)

我很难弄清楚这一点,我有一个简单的MySQL表(test_scores),它有三列,id(学生),日期和考试成绩。
| 身份证|日期|坡度|
| - ------|- ------|- ------|
| 1个|2022年10月20日|A类|
| 第二章|2022年10月20日|B|
| 1个|2022年11月1日|F级|
| 第二章|2022年11月1日|C级|
| 三个|2022年11月1日|A类|
| 1个|2022年12月1日|C级|
我想得到一个学生在下一次考试中得到F的分数。在这个例子中,我想得到下面的输出。
| 身份证|坡度|下一级|
| - ------|- ------|- ------|
| 1个|F级|C级|
我试过:

SELECT id, grade, grade as next_grade FROM test_scores WHERE grade = F;

我只是在学习高级连接和嵌套查询,我只是不知道如何获得下一个等级。任何帮助将不胜感激。

vmpqdwk3

vmpqdwk31#

有很大的优化空间。
首先你要猜一猜,每个学生不可能有很多毕业生,但是学生的数量很大,也不是很多学生有F。
首先你要做的是让所有的学生都拿到F级

select id, `date` from test_scores where grade='F'

在那之后,你需要试着为那些学生找到另一个年级。

select a.id,a.grade,b.grade from 
  (select id,`date`,grade from test_scores where grade = 'F')  a 
   left join
      test_scores b on 
        a.id = b.id and a.date < b.date
where b.grade is not null

这一个给予了F之后的所有分数,如果你有F,A,B,那么它会给出两行分数,但这不应该发生,不是吗?
如果您认为可以有多行,可以用查找替换左连接,但速度会稍慢一些。

select * from 
   (select id, grade,
                     (select grade from test_scores AS b 
                                  where b.id=a.id and a.date < b.date 
                                   order by b.date limit 1
                     ) AS next_grade
        from test_scores AS b 
           where grade = 'F'
    ) AS result
    where result.next_grade is not null

推荐的索引- test_score(id)-我希望你有它。我的意思是在大多数情况下你必须在主列上建立索引。
也许有用test_score(id,date)-但这必须在真实的数据上检查。可能会在10 m+表中有用,但几率很低。只是因为每个学生不可能在他的生活中有很多毕业成绩。
ps.这将只对日期或时间戳列起作用。如果您的列是文本,请将连接替换为

a.id = b.id and 
   DATE_FORMAT(a.date, '%M/%d/%Y') < DATE_FORMAT(b.date, '%M/%d/%Y')

另外,如果你的表真的很大,你可以考虑不做子查询,而是从第一个子查询移到外面,只做左连接。这将这个SQL从索引查找类型转换为索引匹配类型。它可能会也可能不会加速它。

hmmo2u0o

hmmo2u0o2#

使用lead会容易得多,但它需要MySQL 8+。

select id,
       grade,
       next_grade
from (  select id,
               grade,
               lead (grade) over (partition by id order by str_to_date(date,'%m/%d/%y') asc  ) as next_grade
        from test_scores 
      ) as tbl
where  grade='F' ;

https://dbfiddle.uk/k2-FDxQO

相关问题