代码强化
select 列名1,列名2 .. from 表名 我们之前说的查询表指定列的语句
比如对students表,我们可以select students.id,students.name from students;(代表students的属性。用点连接,当然不如省略)
其实我们也可以给表起名而让上句得到简写,select s.id,s.name from students as s;
比如我们现实students的性别列如上,如果我们想得到不重复的结果显示怎么办呢
使用select distinct 列名 from 表名; 去重效果如上
我们也可以在distinct后加多列,所有唯一组合会显示在结果上
where比较运算
我们查询(或更新或删除)后面可以接where 条件
条件判断有如上图几种
比较运算符
等于= (和python不一样,用一个=)
小于< 大于> 小于等于<= 大于等于>= 不等于!= 或<> (没有><)
代码例子如上图,
我们还可以玩select * from students where id%2=0;查询偶数号信息
select * from students where id%2;也会查询奇数信息和python有点像
where逻辑运算
与或非and or not 和python一样
我们写语句需要注意的是where a<5 and >1;这种是错误的,必须写全成where a<5 and a>1;
我们也支持python的连式where 1<a<5;
where模糊查询
我们之前使用的都是条件查询,现在我们使用like实现模糊查询,有点类似正则匹配
使用like %表示任意多个字符串(可以是0个),_表示任意一个字符(匹配必须全部内容)
where范围查询
in 指定数量内容 如 where id in (1,2,3); (只能用小括号)
where x between a and b;表示x在[a,b]的连续区间
同理判断不在范围可以用where a not in (x,xx,xxx);
where a not between A and B;
where空值判断
我们有的数据如果没有设置非空或主键,那可能会有Null值,不管他本来占据字符串或者数值类型,他是个专门的类型,不等于‘’空字符串
我们可以使用where 列名 is null;判断为空
使用where 列名 is not null;判断非空
这里我们还可以使用where 列名;(注意类比判断非空没有where not 列名)
order by排序
常见order by 列名 asc|desc;(asc升序,desc降序)
如果表示升序可以直接order by 列名;
按多组列名排序order by 列名1 asc|desc, 列名2 asc|desc...; 优先按照列1的排序,然后相同的依次按照后续列名内容排列
聚合函数
用于统计,如求平均,最值,求和,数量(默认是不统计NULL,若想统计,需要使用ifnull函数对null值做转换),聚合函数不允许嵌套
select count(列名) from 表名; 统计数量
select max(列名) from 表名; 求该列最大值
select min(列名) from 表名; 求该列最小值
select sum(列名) from 表名; 对该列求和
select avg(列名) from 表名; 求该列平均值
可以和之前的where嵌套,如统计男生人数select count(gender) from students where gender='男';
还可以使用一定程度的组合(非嵌套)如统计平均年龄不用avg
select sum(age)/count(*) from students;
我们这里顺带学习下round函数,round(a,b)把数值a四舍五入,保留小数点后b位,和python一样,
上式求小数点后一位可以写成select round(sum(age)/count(*),1) from students;
group分组
分组,将数据集划分为多干小区域
GROUP BY
如上图,我们可以显示gender列的几个出现过的值显示出来
select gender from students group by gender; (select distinct gender from students效果一样)
如果我们select * from students group by gender;会提示错误(select 后面的内容只能是group by后面出现过或者聚合函数使用过)
group by 还可以和聚合函数结合,比如我们想显示按性别分组后各组的人数:
select gender,count(*) from students group by gender;
更多和where组合,比如获得男女性别的最大年龄:
select gender,max(age) from students where gender in ('男','女') group by gender;
group_concat()+group by 拼接
我们可以通过select gender ,avg(age) from students group by gender;实现按性别分组的平均年龄
如果我们想查询平均值超过三十的性别呢,这时候就需要进一步加条件筛选了,这里我们需要明确的是,where条件是查询的同时进行筛选,而group by是在查询完后进行的分组,如果我们想对分组的结果进行条件筛选,就不能再多用一个where了,而是用having
如上图select gender,avg(age) from students group by gender having avg(age)>30;
最后avg(age)是图17的一个字段,所以我们要把它来和30比较
with rollup统计汇总
比如我们统计性别分组的数量最后加上with rollup会在最后一行多了一个名称null,参数值为总和的数据
select gender,count(*) from students group by gender with rollup;
最后记得分组的字段要出现在select后面
LIMIT限制记录
limit限制取出记录的数量,而且要写在sql语句最后
limit 起始索引,记录条数 (0位默认第一条,起始索引和逗号省略的情况下默认是0)
如上图取出前三条数据
省略起始索引即select * from students limit 3;
所以我们就有了如上的一般查询写法
分页查询
就是上节limit显示的继续
比如我们每2行显示一页select * from students limit 2;
下一页select * from students limit 2,2;
再下一页select * from students limit 4,2;
会得到通项第p页,select * from students limit 2*(p-1),2;但是我们实际使用不能用算式写上面
需要根据p给出具体的数值
select * from 表名 limit m*(p-1),m; 来实现每页m项第p页显示(需要根据p给出具体的数值)
连接查询
使用场景,比如实际项目中,经常多张表,可能需要从多张表共同检索出一些信息,就需要使用连接查询
连接查询有3种,1内连接,两个表匹配的交集部分(通过查找2表相同字段)
2右外连接,两个表的交集和右表特有的数据(数据结构字段以右表基准)
3左外连接,两个表的交集和左表特有的数据(数据结构字段以左表基准)
对于2,3不存在的字段值自动使用null填充
内连接
我们之前有表格students 16行数据7列;
还有表classes数据3行2列
我们使用select * from students inner join classes; 就会发现生成了48行数据9列数据,为什么是这种效果呢?我们看下图
我们使用第一行小明的数据去匹配3次classes数据,其他行同理,最终A inner join B的效果就是A的字段加上B的字段,然后A的行数×B的行数的新表格
我们把2个表的每个数据都互相做关联成为笛卡尔积
之前的48行数据显然不是我们最终想要的,比如我们想把students的cls_id和classes的id对应上,写如上代码select * from students inner join classes where students.cls_id=classes.id;
再比如我们想只获得人名和班级名,可以使用如上代码
select students.name,classes.name from students inner join classes where students.cls_id=classes.id;
其实内连接的where条件的where可以替换为on
比如我们想获得学生所有信息,班级的名字使用
select students.*,classes.name from students inner join classes on students.cls_id = classes.id;
比如我们想获得所有信息按班级名id排序
select * from students inner join classes on students.cls_id = classes.id order by classes.id;
比如我们想按班级id排序再按学号id排序
select * from students inner join classes on studens.cls_id = classes.id order by classes.id,students.id;
外连接
外连接分为左外连接和右外连接
左外连接
主表 left join 从表
一张图用于解释,我们通过cls_id和id匹配,左外连接就会把对应到相同的部分连接起来,没有id匹配到的用null填充
右外连接
从表 right join 主表 on 连接条件 (从表没有对应的内容要填null)
如上图8序号没有对应,需要从表填充null
比如我们students表cls_id有3,4,5,我们使用左外连接会出现上图的几个null
select * from students left join classes on students.cls_id = classes.id;
最后我们分析下,我们学了几种连接,我们什么情况下使用什么连接呢,如果获得2个表都有的信息部分使用内连接,我们想保留左表全部信息,就使用左外连接,同理保留右表使用右外连接
自连接查询(了解)
自连接,表自己和自己连接查询
如上表,存储所有的省市县,aid为其实际id,pid为其父id,比如4广州市属于广东省,那pid就是1
我们想准备如上数据,需要从视频获得一个sql文件,先创建表格结构
这个sql文件并没有创建语句,只是一堆插入,所以我们之前需要创建表结构
我们进入mysql命令行,可以很LOW的复制粘贴如上sql内容,,但是我们有更简便的方法,
输入source areas.sql (不用加逗号),即实现了数据的导入(和我们之前的mysql命令行以外的导入不一样语句)
创建完毕,我们可以统计一共多少个省
select count(*) from areas where pid is null;
如果我们想查询山西省的所有城市
select city.* from areas city inner join areas province on city.pid = province.aid where province.artitle='山西省';
这里我们使用了对重复使用同一个表的不同重命名
子查询
一个查询里又嵌入了一个查询,前者为主查询,后者为子查询
子查询分三类,标量子查询,列子查询,行子查询
标量子查询
我们查询结果是个标量,即一行一列的数据是个值,比如上图子查询avg(age)就得到一个值,值就可以判断等于或者比较
列子查询
返回的是一列数据,子查询就是单独差一列,如上图返回列的话就可以in