一、多表查询
使用单个select 语句从多个表格中取出相关的查询结果,多表连接通常是建立在有相互关系的父子表上;
notice:下列代码参照上条博客用户和身份证关联(一对一)
1、交叉连接
第一个表中的所有行乘以第二个表中的所有行,也就是笛卡尔积
-- 自然连接
-- 隐式语法
select * from card,users;
-- 显式语法
select * from card cross join users;
notice:交叉连接获得的结果是错误的
2、内连接
因为交叉连接获得的结果集是错误的。因此内连接是在交叉连接的基础上
只列出连接表中与连接条件相匹配的数据行,匹配不上的记录不会被列出。
-- 内连接
-- 隐式语法
select * from card,users where users.id = card.user_id;
-- 显示语法
select * from card as c INNER JOIN users as u ON u.id = c.user_id;
3、外连接
(内连接只列出所有对应的信息,不会列出没有的信息)
外链接是以一张表为基表,其他表信息进行拼接,如果有就拼接上,如果没有显示null; 外链接分为左外连接和右下连接。
左外连接: 以关键字左边的表格为基表进行拼接
-- 外链接
-- 左外连接
select * from card as c LEFT JOIN users as u on c.user_id = u.id;
右外连接: 以关键字右边的表格为基表
-- 右外连接
select * from users as u right join card as c on c.user_id = u.id;
二、子查询
某些情况下,当进行查询的时候,需要的条件是另外一个select语句的结果,这个时候就会用到子查询,为了给主查询(外部查询) 提供数据而首先执行的查询(内部查询)被叫做子查询; 子查询分为嵌套子查询和相关子查询。
嵌套子查询:
内部查询的执行独立于外部查询,内部查询仅执行一次,执行完毕后将结果作为外部查询的条件使用(嵌套子查询中的子查询语句可以拿出来单独运行。)
相关子查询:
内部查询的执行依赖于外部查询的数据,外部查询每执行一次,内部查询也会执行一次。每一次都是外部查询先执行,取出外部查询表中的一个元组,将当前元组中的数据传递给内部查询,然后执行内部查询。根据内部查询执行的结果,判断当前元组是否满足外部查询中的where条件,若满足则当前元组是符合要求的记录,否则不符合要求。然后,外部查询继续取出下一个元组数据,执行上述的操作,直到全部元组均被处理完毕。
(notice:可以通过用嵌套循环打印九九乘法表的思想:内部循环条件需要用到外部的变量,每当外部循环进行一次,内部循环也相应执行完成一次(完成表示内部循环完整的执行完一次))
-- 子查询
select student_id from tch_std where teacher_id = 1;-- 先在tch_std 中查询老师id为1的学生id
select * from student where id in (1,2); -- 然后在学生表中查询上条语句所得到的id对应的学生信息
-- 嵌套子查询
select * from student where id in (select student_id from tch_std where teacher_id = 1);
-- 相关子查询
-- 求每一科考试成绩大于平均分的学生的分数
select * from tch_std as a where a.score>(select AVG(b.score) from tch_std as b WHERE a.teacher_id = b.teacher_id);
三、常用函数中的聚合函数
1. count() :求满足列条件的总的行数。
-- COUNT(DISTINCT expr,[expr...])
-- 统计记录的数量
select count(*) as count from score;
-- 统计python大于80分的学生的数量
select count(*) as count from score where python >= 80;
-- 统计总成绩大于240分的学生数量
select count(*) as count from score where (python+mysql+web)>240;
2. sum(): 求总和。
-- SUM([DISTINCT] expr)
-- 统计python总成绩
select sum(python) as sum from score ;
-- 统计各科总成绩
SELECT
sum(python) AS python,
sum(mysql) AS mysql,
sum(web) AS web
FROM
score;
-- 统计一个班级python成绩的平均分
select sum(python)/count(python) as pythpn_avg from score;
3. avg(): 求平均数。
-- AVG([DISTINCT] expr) 求平均数
-- 统计一个班级python成绩的平均分
select avg(python) as python_avg from score;
-- 求一个班级总分平均分
select avg(python+mysql+web) as avg from score;
4. min() 和 max() 求最大值和最小值。
-- MIN([DISTINCT] expr)
-- MAX([DISTINCT] expr)
-- 求班级web的最高分和最低分
select min(web) as web_min from score;
select max(web) as web_max from score;
5. group by 分组。
GROUP BY子句的真正作用在于与各种聚合函数配合使用。它用来对查询出来的数据进行分组。
分组的含义是:把该列具有相同值的多条记录当成一组记录处理,最后只输出一条记录。分组函数忽略空值。
-- 创建手机订单表
create table t_order(id int primary key,product varchar(20),price float(8,2));
insert into t_order values(1,'xiaomi', 1000);
insert into t_order values(2,'xiaomi',1100);
insert into t_order values(3,'huawei',2200);
insert into t_order values(4,'apple',8200);
-- 1.对订单表中商品归类后,显示每一类商品的总价
SELECT product,SUM(price) FROM t_order GROUP BY product;
-- 2.查询商品总价格大于3000的商品
SELECT product,SUM(price) as sum FROM t_order GROUP BY product HAVING sum>2100;
-- 统计一个班中每个学生的总成绩
select id,name,python+mysql+web as total from score;
notice:
(1)、分组函数的重要规则
如果使用了分 组函数,或者使用GROUP BY 的查询:出现在SELECT列表 中的字段,要么出现在聚合函数里,要么出现在GROUP BY 子句中。
(上面的product出现在了group by中,price出现在了聚合函数中)
GROUP BY 子句的字段可以不出现在SELECT列表当中。
(2)、having where 的区别
①、where和having都是用来做条件限定的,
②、WHERE是在分组(group by)前进行条件过滤,
③、HAVING子句是在分组(group by)后进行条件过滤,
④、WHERE子句中不能使用聚合函数,HAVING子句可以使用聚合函数。