MySQL查询操作
SELECT select_expr [,select_expr,...] [
FROM tb_name
[WHERE 条件判断]
[GROUP BY {col_name | postion} [ASC | DESC], ...]
[HAVING WHERE 条件判断]
[ORDER BY {col_name|expr|postion} [ASC | DESC], ...]
[ LIMIT {[offset,]rowcount | row_count OFFSET offset}]
]
select distinct *
from 表名
where ....
group by ... having ...
order by ...
limit start,count
执行顺序为:
- from 表名
- where …
- group by …
- select distinct *
- having …
- order by …
- limit start,count
MySQL查询操作 | 命令行代码 |
---|---|
select查询所有字段、指定字段的数据 | select * from students; select name,age from students; |
消除重复行命令distinct | select distinct gender from students; |
as给字段、表起别名 | select s.name as '姓名',s.age as '年龄' from students as s; |
条件查询where后跟比较运算符、逻辑运算符的用法 | > 、< 、 >= 、 <= 、 = 、 !=、 and 、or、 not |
条件查询中的模糊查询like和范围查询in | name like '%杰' % : 代表任意个字符 _ : 代表一个字符 |
判断is null和非空判断is not null | select * from students where height is (not) null; |
查询中使用order by排序 | 放在 from、where、group by之后 order by 列1 asc ,列2 desc; desc: 降序 asc:升序,默认 |
常用到的聚合函数count、max、min、sum、avg | count(*)\count(列):总数 max(列): 最大值 min(列): 最小值 sum(列) : 求和 avg(列) :求平均 |
分组查询group by + group_concat(字段名)/聚合函数/having | group by: 分组 group_concat: 拼接字符串,拼接字段名 聚合函数: 最大,最小平均,计数,求和 having: 对分组后的结果集进一步筛选 注意: select 列 中只能存放分组函数(比如聚合函数),或是出现在group by子句中的分组标签 where: 对源数据做条件筛选, 不能接聚合函数 having: 是对分组之后的数据做进一步的筛选操作, 有having就一定有group by, 有 group by 不一定有having,接聚合函数 |
分页查询获取部分行的命令limit | limit [start],count 1. 放在查询语句的最后 2. start=(page-1)*count |
连接查询inner/left/right join | inner join on :内连接(结果仅包含符合连接条件的两表中的行) left join on : 左连接(完全显示左表所有的行,如果左表中某行 在右表中没有匹配的行,则右表该行显示NULL) right join on : 右连接(与左连接相反) |
子查询的方法 | 查询中嵌套查询,三种:标量子查询: 子查询的结果为一个值(一行一列) 列子查询: 子查询的结果为一个列(一列多行) 表子查询: 子查询的结果为一个表(多行多列) |
MySQL 查询
创建数据库、数据表
初始化数据
-
1 .创建data_demo数据库
create database data_demo charset=utf8; use data_demo;
-
2 .创建classes表(id,name)
create table classes(id int unsigned not null primary key auto_increment,name varchar(30) not null);
-
3 . 创建students表(id,name,age,height,gender,cls_id,is_delete)
create table students( id int unsigned primary key auto_increment not null, name varchar(20) default '', age tinyint unsigned default 0, height decimal(5,2), gender enum('男','女','中性','保密') default '保密', cls_id int unsigned default 0, is_delete bit default 0 );
准备数据 -
向students表插入数据
insert into students values
(0,'小明',18,180.00,2,1,0),
(0,'小月月',18,180.00,2,2,1),
(0,'彭于晏',29,185.00,1,1,0),
(0,'刘德华',59,175.00,1,2,1),
(0,'黄蓉',38,160.00,2,1,0),
(0,'凤姐',28,150.00,4,2,1),
(0,'王祖贤',18,172.00,2,1,1),
(0,'周杰伦',36,NULL,1,1,0),
(0,'程坤',27,181.00,1,2,0),
(0,'刘亦菲',25,166.00,2,2,0),
(0,'金星',33,162.00,3,3,1),
(0,'静香',12,180.00,2,4,0),
(0,'郭靖',12,170.00,1,4,0),
(0,'周杰',34,176.00,2,5,0);
- 向classes表插入数据
insert into classes values (0, "class_01"), (0, "class_02");
基本查询
- 查询所有字段
select * from 表名;
例:
select * from students;
- 查询指定字段
select 列1,列2,… from 表名;
例:
select name , age from students;
- 使用 as 给字段起别名
- select 字段 as 名字… from 表名;
select name as ‘姓名’, age as ‘年龄’ from students;
- select 表名.字段 … from 表名;
select students.name, students.age from students;
select * from students,classes;
select students.name as ‘姓名’,classes.name as ‘班名’ from students,classes; - 错误的: select name,name from students,classes;
- select 字段 as 名字… from 表名;
- 使用 as 给表起别名
- select 别名.字段 … from 表名 as 别名;
select s.name from students as s;
-失败的: select students.id,students.age from students as s;
- select 别名.字段 … from 表名 as 别名;
- 消除重复行
在select后面列前使用distinct(清楚的; 截然不同的; 明显的)可以消除重复的行- 在select后面,列的前面使用distinct可以消除重复的行
(去重)
select distinct gender from students;
select distinct * from students;
select distinct id from students;
- 物理删除/硬删除 (通过delete from 把记录从表中删除)
delete from classes where id=1;
- 逻辑删除/软删除(用一个字段来表示 这条信息是否已经不能再使用了)
update students set is_delete=1 where name=‘小明’;
- 在select后面,列的前面使用distinct可以消除重复的行
条件查询
使用where子句对表中的数据筛选,结果为true的行会出现在结果集中
语法如下:
select * from 表名 where 条件;
例:
select * from students where id=1;
where后面支持多种运算符,进行条件的处理
- 比较运算符
- 逻辑运算符
- 模糊查询
- 范围查询
- 空判断
比较运算符
- 等于: =
- 大于: >
- 大于等于: >=
- 小于: <
- 小于等于: <=
- 不等于: != 或 <>
查询大于18岁的学生信息
select * from students where age>18;
查询小于18岁的学生信息
select * from students where age<18;
查询小于或者等于18岁的学生信息
select * from students where age<=18;
查询年龄为18岁的所有学生的名字
select * from students where age=18;
– != 或者 <>
select * from students where age!=18;
逻辑运算符
- and
- or
- not
and (并且) 年龄在18和28之间的所有学生信息
select * from students where age>18 and age<28;
失败的 select * from students where age>18 and <28;
18岁以上的女性
select * from students where age>18 and gender=‘女’;
or (或者)
18以上或者身高高过180(包含)以上的学生信息
select * from students where age >18 or height>=180;
not (取反)
不在 18岁以上的女性 这个范围内的信息
select * from students where (not age>18 ) and gender=“女”;
模糊查询
Like
where 列名 like 要查询的数据
- %表示0到多个任意字符
- _表示一个任意字符
查询姓周的学生
select * from students where name like ‘周%’;
查询姓名中 包含 “杰” 字的所有名字
select * from students where name like ‘%杰%’;
查询姓周并且“名”是一个字的学生
select * from students where name like ‘周_’;
查询姓黄或叫靖的学生
select * from students where name like ‘黄%’ or name like ‘%靖%’;
rlike 正则
查询以 周开始的姓名
select * from students where name rlike ‘^周.’;
select * from students where name rlike '杰.’;
范围查询
- in (表示在一个非连续的范围内)
- between … and …表示在一个连续的范围内
查询编号是1或3或8的学生
select * from students where id in(1,3,8);
between … and …表示在一个连续的范围内
查询 年龄在18到34之间的男同学信息
select * from students where (age between 18 and 34) and gender=“男”;
查询 年龄不在在18到34之间的的信息
语法: not between … and … : 不再范围内
select * from students where age not between 18 and 34;
select * from students where not (age between 18 and 34);
空判断
- is null (判断是否为空)
注意:null与’'是不同的
查询身高为空的学生信息
select * from students where height is null;
失败的:select * from students where height=null; - is not null (判非空)
– 查询身高不为空的学生信息
select * from students where height is not null;
select * from students where not (height is null);
优先级
- 优先级由高到低的顺序为:小括号,比较运算符,逻辑运算符
- not>and>or,如果同时出现并希望先算or,需要结合()使用
分析以下sql语句:
select * from students where not age>=18 or height>=180 and gender=“男”;
排序
为了方便查看数据,可以对数据进行排序
语法:
select * from 表名 [where ...] order by 列1 asc|desc [,列2 asc|desc,...]
说明:
- 将行数据按照列1进行排序,如果某些行列1的值相同时,则按照列2排序,以此类推
- 默认按照列值从小到大排列(asc)
- asc从小到大排列,即升序
- desc从大到小排序,即降序
order by 字段
查询未删除学生的信息,按年龄降序排序
select * from students where is_delete=0 order by age desc;
order by 多个字段
查询所有学生信息,按照年龄从小到大、当年龄相同,则身高从高到矮的排序
select * from students order by age asc,height desc;
select * from students order by age ,height desc;
聚合函数
目的:对查询的数据结果集进行统计分析
为了快速得到统计数据,经常会用到如下5个聚合函数
-
求总数
- count(*)表示计算表的总行数
- count(\列)表示计算某列的总行数,假如该列某个值为null则不会统计
统计学生表中总人数有多少人
select count() from students;
统计学生表中,女性有多少人
select count() from students where gender=‘女’;
错误的写法: select name,count(*) from students where gender=2 ;
统计学生表中,height 字段不为空的总人数
select count(height) from students;
-
求最大值
max(列)表示求此列的最大值
查询最大的年龄
select max(age) from students ;
查询女性的最高身高
select max(height) from students where gender=‘女’;
-
求最小值
min(列)表示求此列的最小值
查询最小身高
select min(height) from students; -
求和
sum(列)表示求此列的和
计算所有学生的年龄总和
select sum(age) from students;
-
求平均值
avg(列)表示求此列的平均值
计算未删除女生的总人数及平均年龄
select count(*),avg(age) from students where is_delete=0 and gender=‘女’;
分组查询
在实际业务中,经常会对数据进行分类统计操作,通过 group by 可实现分组,做更精细的聚合统计操作
select * from tbname where 条件 group by…having 条件…
-
group by
group by的含义:将查询结果按照1个或多个字段进行分组,字段值相同的为一组
group by可用于单个字段分组,也可用于多个字段分组
注意: select 列 中只能存放分组函数(比如聚合函数),或是出现在group by子句中的分组标签
select gender from students group by gender;
根据gender字段来分组,gender字段的全部值有4个’男’,‘女’,‘中性’,‘保密’,所以分为了4组 当group by单独使用时,只显示出每组的第一条记录。 假如要显示表中的列,则只能显示分组中的列 -
group by + group_concat()
group_concat(字段名)可以作为一个输出字段来使用
表示分组之后,根据分组结果,使用group_concat()来放置每一组的某字段的值的集合
例1:统计出同种性别的学生姓名
select gender from students group by gender;
select gender,group_concat(name) from students group by gender;
例2:统计出同种性别的学生id
select gender,group_concat(id) from students group by gender;
-
group by + 聚合函数
通过group_concat()的启发,我们既然可以统计出每个分组的某字段的值的集合,那么我们也可以通过聚合函数来对这个值的集合做一些操作
例3:按性别分组,统计出每组的平均年龄
select gender,avg(age) from students group by gender;
例4:按性别分组,统计出每组的人数
select gender,count(*) from students group by gender;
-
group by + having
having 条件表达式:分组查询完后,再指定一些条件对分组后的查询结果进行过滤
having作用和where相似,但having只能用于group by,且having可以使用聚合函数
例5:按性别分组,分别统计出平均年龄超过30岁的组的总人数
select gender ,count() from students group by gender having avg(age)>30;
错误:select gender ,count() from students group by gender where age>30;
-
group by + with rollup
with rollup的作用是:在最后新增一行,来记录当前列里所有记录的总和
select gender,count(*) from students group by gender with rollup;
select gender,group_concat(age) from students group by gender with rollup;
分页查询
- 获取部分行
当数据量过大时,通过分批、分页加载数据既能提升加载速度,也可更好显示查询结果
语法
select * from 表名 limit start,count;
说明
从start位置开始,获取count条数据
limit 必须放在查询的最后面
例1:查询前3行男生信息
select * from students where gender=1 limit 3;
select * from students where gender=1 limit 0,4;
- 分页
已知:每页显示m条数据,当前显示第n页
求第n页的数据
select * from students where is_delete=0 limit (n-1)*m,m
常用于python语句中,与逻辑循环for配合使用
连接查询
当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回
mysql支持三种类型的连接查询,分别为:
- 内连接查询:查询的结果为两个表匹配到的数据
- 左连接查询:查询的结果为两个表匹配到的数据,左表特有的数据,对于右表中不存在的数据使用null填充
- 右连接查询:查询的结果为两个表匹配到的数据,右表特有的数据,对于左表中不存在的数据使用null填充
语法
select * from 表1 inner或left或right join 表2 on 表1.列 = 表2.列
例1:使用内连接查询班级表与学生表
select * from students inner join classes on students.cls_id = classes.id;
例2:使用左连接查询班级表与学生表
此处使用了as为表起别名,目的是编写简单
select * from students as s left join classes as c on s.cls_id = c.id;
例3:使用右连接查询班级表与学生表
select * from students as s right join classes as c on s.cls_id = c.id;
例4:查询学生姓名及班级名称
select s.name,c.name from students as s inner join classes as c on s.cls_id = c.id;
自关联查询
设计省信息的表结构provinces
- id
- title
- proid
设计市信息的表结构citys
- id
- title
- proid
设计区县信息表结构areas
- id
- title
- proid
title表示名称,proid表示所属上一级的id值,比如citys.proid 是对应所属省份的id,areas.proid对应的是所属城市的id值
问题:
能不能将三个表合成一张表呢?
思考:
观察三张表发现,表的结构都是一样的,存储的都是地区信息,而且每种信息的数据量有限
意义:
假如合成一张表,即可减少创建表的开销,也用不着多个表关联查询
答案:
定义表areas,结构如下
- id
- atitle
- pid
说明:
因为省没有所属的省份,所以可以填写为null
城市所属的省份pid,填写省所对应的编号id
区县所属的城市pid,填写城市所对应的编号id
这就是自关联,表中的某一列,关联了这个表中的另外一列,但是它们的业务逻辑含义是不一样的,城市信息的pid引用的是省信息的id
创建areas表的语句如下:
create table areas(
aid int primary key,
atitle varchar(20),
pid int
);
因为数据量比较大,这里从外部sql文件areas.sql中导入数据
链接:https://pan.baidu.com/s/1m3c8Fg1Gobe4HpcYLvMyHA
提取码:76wv
source areas.sql;
查询一共有多少个省
select count() from areas where pid is null;
例1:查询省的名称为“山西省”的所有城市
select city. from areas as city
inner join areas as province on city.pid=province.aid
where province.atitle=‘山西省’;
例2:查询市的名称为“广州市”的所有区县
select dis.* from areas as dis
inner join areas as city on city.aid=dis.pid
where city.atitle=‘深圳市’;
子查询
在一个 select 语句中,嵌入了另外一个 select 语句, 那么被嵌入的 select 语句称之为子查询语句
- 主查询
主要查询的对象,第一条 select 语句 - 主查询和子查询的关系
子查询是嵌入到主查询中
子查询是辅助主查询的,要么充当条件,要么充当数据源
子查询是可以独立存在的语句,是一条完整的 select 语句 - 子查询分类
标量子查询: 子查询返回的结果是一个值(一行一列)
列子查询: 返回的结果是一列(一列多行)
行子查询: 返回的结果是一行(一行多列)
表子查询: 返回的结果是一个临时表(多行多列)
标量子查询
例1: 查询大于平均年龄的学生
select * from students where age > (select avg(age) from students);
列级子查询
例2: 查询有班级名称的学生信息
找出班级表中的班级 id
找出学生表中有对应班级的名字
select name from students where cls_id in (select id from classes);
行级子查询(了解)
例3: 查找班级年龄大于平均年龄,且身高大于平均身高的学生
select * from students where (height,age) = (select max(height),max(age) from students);
表子查询(了解)
例4: 查询编号小于6的男性同学的姓名
select name from (select gender,name from students where id<6) as s where gender=“男”;
练习:
关卡一:
首先创建student和score表,添加基本数据,用于查询演练
创建student表SQL代码如下:
create table student(
id int(10) not null unique primary key,
name varchar(20) not null,
gender varchar(4),
birth year,
department varchar(20),
address varchar(50)
);
创建score表SQL代码如下:
create table score(
id int(10) not null unique primary key auto_increment,
stu_id int(10) not null,
c_name varchar(20),
grade int(10)
);
向student表插入记录的insert语句如下:
insert into student values
( 901,'张老大','男',1985,'计算机系','北京市海淀区'),
( 902,'张老二', '男',1986,'中文系', '北京市昌平区'),
( 903,'张三', '女',1990,'中文系', '湖南省永州市'),
( 904,'李四', '男',1990,'英语系', '辽宁省阜新市'),
( 905,'王五', '女',1991,'英语系', '福建省厦门市'),
( 906,'王六', '男',1988,'计算机系', '湖南省衡阳市');
向score表插入记录的insert语句如下:
insert into score values
(NULL,901, '计算机',98),
(NULL,901, '英语', 80),
(NULL,902, '计算机',65),
(NULL,902, '中文',88),
(NULL,903, '中文',95),
(NULL,904, '计算机',70),
(NULL,904, '英语',92),
(NULL,905, '英语',94),
(NULL,906, '计算机',90),
(NULL,906, '英语',85);
题1 查询student表的所有记录
题2 查询student表的第2条到第4条记录
题3 从student表查询所有学生的学号(id)、姓名(name)和院系(department)的信息
题4 从student表中查询计算机系和英语系的学生的信息
题5 从student表中查询年龄22~28岁的学生信息
提示: year(now()) 表示取出当前的年份
关卡二
继续用关卡一的数据表进行查询演练
题1 从student表中查询每个院系有多少人
题2 从score表中查询每个科目的最高分
题3 查询李四的考试科目(c_name)和考试成绩(grade)
题4 用连接的方式查询所有学生的信息和考试信息
题5 查询每个学生的总成绩
题6 查询每个考试科目的平均成绩
题7 查询计算机成绩低于95的学生信息
关卡三
继续使用关卡一的数据进行查询演练
题1 查询计算机考试成绩按从高到低进行排序
题2 查询姓张或者姓王的同学的姓名、院系和考试科目及成绩
题3 查询都是湖南的学生的姓名、年龄、院系和科目及成绩
提示:year(now()) 表示取出当前的年份