文章目录
数据查询语言
这章例子:
select 字段列表 from 表名列表
[ where 条件列表 ]
[ group by 分组字段列表 ]
[ having 分组后条件列表 ]
[ order by 排序字段列表 ]
[ limit 分页参数 ];
- 基本查询(不带任何条件)
- 条件查询(where)
- 聚合函数(count、max、min、avg、sum)
- 分组查询(group by)
- 排序查询(order by)
- 分页查询(limit)
基础查询
查询多个字段
select 字段1, 字段2, 字段3 ... from 表名 ;
或
SELECT * FROM 表名 ;
*
号代表查询所有字段,在实际开发中尽量少用(不直观、影响效率)。
字段设置别名
select 字段1 [ 别名1 ] , 字段2 [ 别名2 ] ... from 表名;
去除重复记录
select distinct 字段列表 from 表名;
条件查询
支持:
- 比较运算符
- 逻辑运算符
_
占位符,一条下划线占一个位%
通配符,相当于正则
例如:
- 查询年龄在15岁(包含) 到 20岁(包含)之间的员工信息
select * from emp where age >= 15 && age <= 20;
- 查询姓名为两个字的员工信息
select * from emp where name like '__';
- 查询身份证号最后一位是 X 的员工信息
select * from emp where idcard like '%X';
聚合函数
将一列数据作为一个整体,进行纵向计算
常见的聚合函数
函数 | 功能 |
---|---|
count | 统计数量 |
max | 最大值 |
min | 最小值 |
avg | 平均值 |
sum | 求和 |
select 聚合函数(字段列表) from 表名 ;
注意:NULL 值是不参与所有聚合函数运算的
例如:
- 统计该企业员工数量
select count(idcard) from emp; -- 统计的是idcard字段不为null的记录数
- 统计西安地区员工的年龄之和
select sum(age) from emp where workaddress = '西安';
分组查询
SELECT 字段列表 FROM 表名 [ WHERE 条件 ] GROUP BY 分组字段名 [ HAVING 分组后过滤条件 ];
where 与 having 区别
- 执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组之后对结果进行过滤
- 判断条件不同:where不能对聚合函数进行判断,而having可以
注意:
- 分组之后,查询的字段一般为聚合函数和分组字段,查询其他字段无任何意义
- **执行顺序: where > 聚合函数 > having **
- 支持多字段分组, 具体语法为:
group by columnA,columnB
例子:
- 根据性别分组 , 统计男性员工 和 女性员工的数量
select gender, count(*) from emp group by gender;
- 查询年龄小于45的员工 , 并根据工作地址分组 , 获取员工数量大于等于3的工作地址
select workaddress, count(*) address_count from emp where age < 45 group by workaddress having address_count >= 3;
- 统计各个工作地址上班的男性 及 女性员工的数量
select workaddress, gender, count(*) '数量' from emp group by gender , workaddress;
+-------------+--------+------+
| workaddress | gender | 数量 |
+-------------+--------+------+
| 北京 | 女 | 4 |
| 北京 | 男 | 4 |
| 上海 | 男 | 2 |
| 上海 | 女 | 1 |
| 天津 | 女 | 1 |
| 江苏 | 男 | 2 |
| 西安 | 女 | 1 |
| 西安 | 男 | 1 |
+-------------+--------+------+
8 rows in set (0.07 sec)
排序查询
select 字段列表 from 表名 order by 字段1 排1 序方式1 , 字段2 排序方式2 ;
排序方式:
asc
:升序(默认)desc
:降序
例如:
- 根据年龄对公司的员工进行降序排序
select * from emp order by age desc;
- 根据年龄对公司的员工进行升序排序 , 年龄相同 , 再按照入职时间进行降序排序
select * from emp order by age asc, entrydate desc;
分页查询
分页操作在业务系统开发时,也是非常常见的一个功能,我们在网站中看到的各种各样的分页条,后台都需要借助于数据库的分页操作
select 字段列表 from 表名 limit 起始索引, 查询记录数 ;
- 起始索引从0开始,起始索引 = (查询页码 - 1)* 每页显示记录数。
- 分页查询是数据库的方言,不同的数据库有不同的实现,MySQL 中是 LIMIT。
- 如果查询的是第一页数据,起始索引可以省略,直接简写为 limit 10
例子:
- 查询第1页员工数据, 每页展示10条记录
select * from emp limit 0,10;
select * from emp limit 10;
- 查询第2页员工数据, 每页展示10条记录 —> ( 2 − 1 ) ∗ 10 = 10 (2 - 1)*10=10 (2−1)∗10=10
select * from emp limit 10,10;
执行顺序
经典案例
摘至黑马 MySQL 文档
(1)查询年龄为20,21,22,23岁的员工信息
select * from emp where gender = '女' and age in(20,21,22,23);
(2)查询性别为 男 ,并且年龄在 20-40 岁(含)以内的姓名为三个字的员工
select * from emp where gender = '男' and ( age between 20 and 40 ) and name like '___';
(3)统计员工表中, 年龄小于60岁的 , 男性员工和女性员工的人数
select gender, count(*) from emp where age < 60 group by gender;
(4)查询所有年龄小于等于35岁员工的姓名和年龄,并对查询结果按年龄升序排序,如果年龄相同按入职时间降序排序
select name , age from emp where age <= 35 order by age asc, entrydate desc;
(5)查询性别为男,且年龄在20-40 岁(含)以内的前5个员工信息,对查询的结果按年龄升序排序,年龄相同按入职时间升序排序
select * from emp where gender = '男' and age between 20 and 40 order by age asc, entrydate asc limit 5 ;
多表查询
多表关系
一对一
- 例子:用户 与 用户详情的关系
- 关系:一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率
- 实现:在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)
一对多
- 例子:部门 和 员工的关系
- 关系:一个部门对应多个员工,一个员工对应一个部门
- 实现:在**⌈** 多 ⌋的一方建立外键,指向⌈ 一 **⌋**的一方的主键
多对多
- 例子:学生 与 课程的关系
- 关系:一个学生可以选修多门课程,一门课程也可以供多个学生选择
- 实现:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键
连接
在查询时数据的冗杂会导致效率低下,必须要筛掉笛卡尔积中的大部分情况
建立连接查询可以有效去除冗杂的笛卡尔积
- 内连接:相当于查询A、B交集部分数据
- 左外连接:查询左表所有数据,以及两张表交集部分数据
- 右外连接:查询右表所有数据,以及两张表交集部分数据
- 自连接:当前表与自身的连接查询,自连接必须使用表别名
内连接
查询两表交集部分数据
隐式内连接
select 字段列表 from 表1, 表2 where 条件... ;
显式内连接
select 字段列表 from 表1 [ INNER ] join 表2 on 连接条件 ... ;
例如:
查询每一个员工的姓名 , 及关联的部门的名称
- 隐式内连接
select e.name,d.name from emp e , dept d where e.dept_id = d.id;
- 显式内连接
select e.name, d.name from emp e join dept d on e.dept_id = d.id;
左外连接
查询左表(表1)所有数据,以及两张表交集部分数据
select 字段列表 from 表1 left [ outer ] join 表2 on 条件 ... ;
右外连接
查询右表所有数据,以及两张表交集部分数据
select 字段列表 from 表1 right [ outer ] join 表2 on 条件 ... ;
自连接
自己连接自己
select 字段列表 from 表A 别名A join 表A 别名B on 条件 ... ;
例如:
emp 表结构
+----+--------+-----+--------------+--------+------------+-----------+---------+
| id | name | age | job | salary | entrydate | managerid | dept_id |
+----+--------+-----+--------------+--------+------------+-----------+---------+
| 1 | 金庸 | 66 | 总裁 | 20000 | 2000-01-01 | NULL | 5 |
| 2 | 张无忌 | 20 | 项目经理 | 12500 | 2005-12-05 | 1 | 1 |
| 3 | 杨逍 | 33 | 开发 | 8400 | 2000-11-03 | 2 | 1 |
| 4 | 韦一笑 | 48 | 开发 | 11000 | 2002-02-05 | 2 | 1 |
| 5 | 常遇春 | 43 | 开发 | 10500 | 2004-09-07 | 3 | 1 |
| 6 | 小昭 | 19 | 程序员鼓励师 | 6600 | 2004-10-12 | 2 | 1 |
+----+--------+-----+--------------+--------+------------+-----------+---------+
查询所有员工 emp 及其领导的名字 emp , 如果员工没有领导, 也需要查询出来
select a.name '员工', b.name '领导' from emp a left join emp b on a.managerid = b.id;
结果:
+--------+--------+
| 员工 | 领导 |
+--------+--------+
| 金庸 | NULL |
| 张无忌 | 金庸 |
| 杨逍 | 张无忌 |
| 韦一笑 | 张无忌 |
| 常遇春 | 杨逍 |
| 小昭 | 张无忌 |
+--------+--------+