在MySQL中,
把成绩低于总平均成绩的女同学的的成绩提高5%
#首先我们需要确定[成绩表]里是否存在[外键],
如果不存在,那么我们直接进行update语句即可,
如果存在[外键],我们是没办法进行更改成绩的,
那么我们需要先把这个[成绩表]备份一下,
备份/复制一个表的语法是:
create table 新表名 select * from 旧表名;
相应的如果[成绩表]名为”sc”的话,就随便创建一个新表,表明为”sc1″,那么语法就是:
create table sc1 select * from sc;
备份完[成绩表]之后,
就可以进行更改操作了,
根据题目,首先我们需要确定几个条件,
第一,总平均成绩
第二,成绩低于总平均成绩的人
第三,所有的女生
那么,好,求出平均成绩的语法是:
select avg(成绩) from 表名;
在[成绩表]里,成绩的字段名为:degree,并且需要在刚才的新表中才可以更改,所以就以[sc1]表为例,具体语法:
select avg(degree) from sc1;
第一步到此为止。
接着,成绩低于总平均成绩的人,语法:
where degree < (select avg(degree) from sc1);
第二步到底结束。
接着,所有的女生,有性别的表是[学生表],所以我们要在[学生表]里查询,语法:
select * from student where ssex="女";
但是,我们需要先要想一想,我们查出了所有的女生,但是我们肯定不需要她们所有的信息,只需要其中的一个项(字段)即可,[学生表]和[成绩表]里都有的字段是[学号]”sno”,那么就用[学号]这个字段即可。所以上面的语法要改为:
select sno from student where ssex="女";
那么,好,第三步到此结束。
更新/修改 的语句是:
update 表名 set 列名=表达式... where 条件语句;
所以完整的语句是:
update sc1 set degree=degree*1.05
where sno in (select sno from student where ssex="女")
and degree<(select * from (select avg(degree) as degree from sc1) as a);
好,没了,就这些。
细心的话,会注意到,作为条件的话,一般作为条件的都是一个数据(单个数据),比如[平均成绩]是一个数,比如性别”女”。
但是,
性别为”女”的人的学号是一整列学号,竟然也可以作为条件查询!我还不知道答案的时候,思来想去,不知道如何把一整列学号当作一个条件来使用。
结果一看答案。
惊了!
竟然只用了一个”in”就可以把一整列当作一个条件。
谢谢评论里的提醒,确实是我有地方写错了,这个题我是用Oracle写出来的,我没想到用mysql写出来会出错。
上面的语句已经使用mysql的语法更正。下面说一下会出错的地方有哪些?
两个报错:
报错一:
> 1093 - You can't specify target table 'sc' for update in FROM clause
> 时间: 0.001s
报错翻译是:不能在FROM子句中为UPDATE指定目标表‘sc’。
也就是说,mysql里面,需要update的表和update后面where条件里面的子查询不能是同一个表。(我update的表是sc1,update后面where里面的子查询也是sc1)
这样写会报错:
update sc1 set degree=degree*1.05
where sno in (select sno from student where ssex="女")
and degree<(select avg(degree) as degree from sc1);
那怎么解决呢?只要不是同一个表就行的话,那就把update后面where里面的子查询外面再套一个select。
这样的话,update后面where语句里面的子查询就成了一张临时表。from后面跟一个表名,这一步会让mysql去硬盘里查找是否存在这张表,若存在,我就把这个表的数据形成结果集,拿出来放到内存里,现在我从外面再套一个select from,就是用内存里面的这个结果集里面去查询了,不再是直接从硬盘里去查找了。
报错二:
> 1248 - Every derived table must have its own alias
> 时间: 0s
报错翻译:每个派生表都必须有自己的别名。
也就是说,mysql里面的嵌套子查询需要一个别名。这个报错我在Oracle里面没有见过。现在发现mysql会有这样的问题。
我这样写就会报错:
select * from (select avg(degree) as degree from sc1);
也就是说,外面的这个select from后面的临时表需要一个别名。
如何解决这个报错呢?
解决办法就是,每当遇到一个子查询时,外面的from都加一个别名即可。(别名就是另一个名字,是什么无所谓,只要你理解你知道即可,你给伙伴看的时候一眼就知道啥意思就行,当然了项目中的话,最好别名是有意义的。)
如下:
select * from (select avg(degree) as degree from sc1) as a;