文章目录
SQL语句的报错汇总
相关的表内容如下:
1052 - Column ‘xxx’ in IN/ALL/ANY subquery is ambiguous
题目:查询" 01 “课程⽐” 02 "课程成绩⾼的学⽣的信息及课程分数
出错的情况:
select student.SId,student.Sname,student.Sage,student.Ssex,s3.CId,s3.score
from student
where SId in
(select s1.SId
from sc as s1
INNER JOIN sc as s2 on s1.SId=s2.SId
where s1.score>s2.score and s1.CId=1 and s2.CId=2) and s3.CId in (1,2);
select student.SId,student.Sname,student.Sage,student.Ssex,s3.CId,s3.score
from student
inner join sc as s3 on student.SId=s3.SId
where SId in
(select s1.SId
from sc as s1
INNER JOIN sc as s2 on s1.SId=s2.SId
where s1.score>s2.score and s1.CId=1 and s2.CId=2) and s3.CId in (1,2);
第一部分的SQL语句是没有报错的,只是没有返回题目要求的课程分数信息
在试图加上分数时改写成了第二部分的SQL语句,结果报错,错误信息为
> 1052 - Column 'SId' in IN/ALL/ANY subquery is ambiguous
> 时间: 0s
原因:sc表与student表中都有SId字段,这时候where子句里的SId如果不加表名
SQL无法判断该字段属于哪个表,只要加上表名.字段名即可
select student.SId,student.Sname,student.Sage,student.Ssex,s3.CId,s3.score
from student
inner join sc as s3 on student.SId=s3.SId
where student.SId and s3.SId in
(select s1.SId
from sc as s1
INNER JOIN sc as s2 on s1.SId=s2.SId
where s1.score>s2.score and s1.CId=1 and s2.CId=2) and s3.CId in (1,2);
1248 - Every derived table must have its own alias
原因:如同字面意思,子查询产生的表必须要有一个名字,否则报错
(select sc.cid,round(avg(sc.score),2) as avg_sc
from sc
group by cid
order by avg_sc desc) as b
子查询与联结查询
上文有提到过,子查询的效率是最低的,因此应该尽量替换成效果相同的联结查询
select stu.* from student as stu
where SId in
(select SId from sc where CId in
(select TId from teacher where Tname="张三")
);
select stu.* from student as stu
inner join sc on stu.SId=sc.SId
inner join teacher on sc.CId=teacher.TId and Tname="张三";
外部联结的注意事项
使用left join … on …时,如果像第一段代码这样加where,结果是联结完的表进行筛选
这样一来,left join失去了意义,student表里的学生信息不会完全显示
select stu.SId,stu.Sname,sc2.score as CId1,sc3.score as CId2,sc4.score as CId3,
round(avg(sc1.score),2) as avg_score
from student as stu
left join sc as sc1 on stu.SId=sc1.SId
left join sc as sc2 on stu.SId=sc2.SId
left join sc as sc3 on stu.SId=sc3.SId
left join sc as sc4 on stu.SId=sc4.SId
where sc2.CId=1 and sc3.CId=2 and sc4.CId=3
group by SId order by avg_score desc;
为了让student表里的学生信息完全显示,建议使用left join … on … and …
select stu.SId,stu.Sname,sc2.score as CId1,sc3.score as CId2,sc4.score as CId3,
round(avg(sc1.score),2) as avg_score
from student as stu
left join sc as sc1 on stu.SId=sc1.SId
left join sc as sc2 on stu.SId=sc2.SId and sc2.CId=1
left join sc as sc3 on stu.SId=sc3.SId and sc3.CId=2
left join sc as sc4 on stu.SId=sc4.SId and sc4.CId=3
group by SId order by avg_score desc;
UNION联合查询的注意事项
使用union做联合查询时,只可以在结尾的select语句添加group by,order by等子句
为了避开SQL语法上的这个格式,可以使用以下的方法应对这个问题
select * from
(select sid,cid,score from sc
group by sid,cid having cid=1
order by score desc limit 3) as s1
union
select * from
(select sid,cid,score from sc
group by sid,cid having cid=2
order by score desc limit 3) as s2
union
select * from
(select sid,cid,score from sc
group by sid,cid having cid=3
order by score desc limit 3) as s3;
即把分好组排完序的表,用作子查询并起名为新表,再用union把这三个select联合查询
(select sid,cid,score from sc
group by sid,cid having cid=1
order by score desc limit 3)
union
(select sid,cid,score from sc
group by sid,cid having cid=2
order by score desc limit 3)
union
(select sid,cid,score from sc
group by sid,cid having cid=3
order by score desc limit 3);
in的技巧
当where里的条件字段与某个表中的字段相同时,可以将条件字段括起来这样写
select * from zhubo
where (zhubo_id,level) in (select zhubo_id,max(level) from zhubo group by zhubo_id);
如果不用这个技巧的笨重写法或许是这样写的
select * from zhubo
where zhubo_id in (select zhubo_id from zhubo group by zhubo_id) and
level in (select max(level) from zhubo group by zhubo_id);
as的注意事项
as用于给表起别名,可以用来简化SQL语句。不过需要注意,如果给某个表起了别名,再用回原来的名字去查找字段是不行的
SQL语句中的行转列
SQL查询里的行转列并不复杂,不过需要用到case when
class_id | grade | rate |
---|---|---|
1 | primary | 70% |
1 | middle | 65% |
1 | high | 72% |
2 | primary | 69% |
2 | middle | 63% |
2 | high | 74% |
class_id | primary | middle | high |
---|---|---|---|
1 | 70% | 65% | 72% |
2 | 69% | 63% | 74% |
select class_id,
max(CASE WHEN grade = 'primary' THEN rate ELSE 0 END) as 'primary',
max(CASE WHEN grade = 'middle' THEN rate ELSE 0 END) as 'middle',
max(CASE WHEN grade = 'high' THEN rate ELSE 0 END) as 'high'
from mst_class
group by class_id;
update语句里嵌入select
update语句里是可以写子查询语句的
UPDATE usrinfo
set age=(select age from test where username="aaa")
where username="aaa";
但是这个子查询语句是不可以从update的这张表里进行查询的
如果子查询里涉及到联结update的这张表会出现错误,因此需要其他的写法
update mst_b as up,(
select mst_a.key,mst_a.value from mst_a join mst_b on mst_a.key = mst_b.key
) as b
set up.value = b.value where up.key = b.key
MySQL里update是可以对多个表进行更改的,利用这一点,可以将子查询的表拽入
用于实现某些复杂的联结查询与表更改的需求