复杂分组查询举例
子查询:把select查询结果当作数据使用时,这种结构就是子查询
- 子查询练习
-- 子查询练习:查询学生成绩在70分以上的学生学号和姓名
select stu_id as id, stu_name as 姓名 from tb_student where stu_id in (select cc_sid from tb_cc_log where cc_score>70);
-- 子查询在修改中的应用:将张三的1001课程成绩改成99分
update tb_cc_log set cc_score=99 where cc_sid=(select stu_id from tb_student where stu_name='张三');
- 子查询容易犯错的地方:不能在同一张表中进行查询和修改操作。如果一定要这样操作,可以通过select查询语句备份一个新表,然后给新表取别名,进行操作即可,示例如下:
- 查询练习举例总结:
- 注意:如果遇到要进行计算的地方,可能这个位置有空值,可以用:ifnull(字段名,0)来表示该字段,如果遇到空值,就会理解为0处理。
连接查询:
1、把多张表的信息联合起来查询,分为三种;
2、连接的时候会出现笛卡尔积的现象(ABC 123——A1A2A3B1B2B3C1C2C3);
3、连接条件就是用来处理笛卡尔积的现象,避免冗余的,通过内连接查询示例如下
(连接条件中条件字段格式:表明.字段名):
-
内连接查询(inner join)
内连接的查询结果是 多张表中 满足连接条件的数据信息。 -
外连接查询(outer join):可以连接多个表。
- 左外连接(left outer join):查询结果显示左表中的全部数据,右表中只显示满足连接条件的,如果左表中的数据右表没有连接点,那右表填充空值null
- 右外连接(right outer join):查询结果显示右表中的全部数据,左表中只显示满足连接条件的,如果右表中的数据左表没有连接点,那左表填充空值null
-
全连接(full join)
1、MySQL不支持全连接操作,但是全连接的本质就是想把两张表的数据全部显示出来。
2、解决方法就是通过MySQL中的合并连接操作来解决全连接的问题,union 和 union all,union合并的时候会过滤掉重复项。union举例(其实union 和 union all 本质就是把左连接和有链接放在一起合并之后就会有全部显示的效果了):
-
自连接:有时候需要在同一张表当中查询两次才能获得想要的信息,这时候就要通过自连接将表本身和自己连接起来,可以通过重命名加以区别,自连接通过下面一个例子就能说明白:
练习
-- 内连接查询:查询学生表和成绩表,展示学生id、学生姓名、学生学科id、学生学科成绩。
select tb_student.stu_id,tb_student.stu_name,tb_cc_log.cc_cid,tb_cc_log.cc_score from tb_student inner join tb_cc_log
on tb_student.stu_id=tb_cc_log.cc_sid;
-- 练习左连接查询:查询学生姓名、选课名称、选课成绩。
select tb_student.stu_name 姓名,tb_c_class.cl_name 课程,tb_cc_log.cc_score 成绩
from tb_student left join tb_cc_log on tb_student.stu_id=tb_cc_log.cc_sid
left join tb_c_class on tb_c_class.cl_id=tb_cc_log.cc_cid;
-- 练习左连接查询:查询所有学生的总成绩
select tb_student.stu_name 姓名,sum(tb_cc_log.cc_score) 总成绩
from tb_student left join tb_cc_log on tb_student.stu_id=tb_cc_log.cc_sid
group by tb_cc_log.cc_sid;
-- 练习左连接查询:查询所有学生的总成绩大于300的学生
select tb_student.stu_name 姓名,sum(tb_cc_log.cc_score) 总成绩
from tb_student left join tb_cc_log on tb_student.stu_id=tb_cc_log.cc_sid
group by tb_cc_log.cc_sid having sum(ifnull(tb_cc_log.cc_score,0))>300;