原文: http://blog.gqylpy.com/gqy/251
"
目录
# 语法 select 字段 1, 字段 2 ... from 表名 where 条件 group by field having 筛选 order by field limit 限制条数重点在于关键字的执行优先级:
from
where
group by
having
select
distinct
order by
limit1. 找到表:from
2. 拿着where指定的约束条件,去文件(表)中取出一条条记录
3. 将取出的一条条记录进行分组group by,如果没有group by, 则整体作为一组
4. 将分组的结果进行having过滤
5. 执行select
6. 去重
7. 将结果按条件排序:order by
8. 限制结果的显示条数
-
company.employee
-
员工id id int
-
姓名 name varchar
-
性别 sex enum
-
年龄 age int
-
入职日期 hire_date date
-
岗位 post varchar
-
职位描述 post_comment varchar
-
薪水 salary double
-
办公室 office int
-
部门编号 depart_id int
-
# 创建员工表
-
mysql>
create
table employee(
-
->
id
int primary
key auto_increment,
-
->
name
varchar(
20)
not
null,
-
-> sex enum(
'male',
'female')
not
null
default
'male',
-
-> age
int(
3)
unsigned
not
null
default
28,
-
-> hire_date
date
not
null,
-
-> post
varchar(
50),
-
-> post_comment
varchar(
100),
-
-> salary
double(
15,
2),
-
-> office
int,
-
-> depart_id
int
-
-> );
-
Query OK, 0 rows affected (0.04 sec)
-
-
mysql> desc employee;
-
+
--------------+-----------------------+------+-----+---------+----------------+
-
| Field | Type | Null | Key | Default | Extra |
-
+
--------------+-----------------------+------+-----+---------+----------------+
-
| id | int(11) | NO | PRI | NULL | auto_increment |
-
| name | varchar(20) | NO | | NULL | |
-
| sex | enum('male','female') | NO | | male | |
-
| age | int(3) unsigned | NO | | 28 | |
-
| hire_date | date | NO | | NULL | |
-
| post | varchar(50) | YES | | NULL | |
-
| post_comment | varchar(100) | YES | | NULL | |
-
| salary | double(15,2) | YES | | NULL | |
-
| office | int(11) | YES | | NULL | |
-
| depart_id | int(11) | YES | | NULL | |
-
+
--------------+-----------------------+------+-----+---------+----------------+
-
10 rows in
set (
0.00 sec)
-
-
-
# 插入记录
-
# 三个部门:教学,销售,运营
-
mysql>
insert
into employee(
name ,sex,age,hire_date,post,salary,office,depart_id)
values
-
-> (
'egon',
'male',
18,
'20170301',
'老男孩驻沙河办事处外交大使',
7300.33,
401,
1),
-
-> # 以下是教学部
-
-> (
'alex',
'male',
78,
'20150302',
'teacher',
1000000.31,
401,
1),
-
-> (
'wupeiqi',
'male',
81,
'20130305',
'teacher',
8300,
401,
1),
-
-> (
'yuanhao',
'male',
73,
'20140701',
'teacher',
3500,
401,
1),
-
-> (
'liwenzhou',
'male',
28,
'20121101',
'teacher',
2100,
401,
1),
-
-> (
'jingliyang',
'female',
18,
'20110211',
'teacher',
9000,
401,
1),
-
-> (
'jinxin',
'male',
18,
'19000301',
'teacher',
30000,
401,
1),
-
-> (
'xiaomage',
'male',
48,
'20101111',
'teacher',
10000,
401,
1),
-
-> # 以下是销售部
-
-> (
'歪歪',
'female',
48,
'20150311',
'sale',
3000.13,
402,
2),
-
-> (
'丫丫',
'female',
38,
'20101101',
'sale',
2000.35,
402,
2),
-
-> (
'丁丁',
'female',
18,
'20110312',
'sale',
1000.37,
402,
2),
-
-> (
'星星',
'female',
18,
'20160513',
'sale',
3000.29,
402,
2),
-
-> (
'格格',
'female',
28,
'20170127',
'sale',
4000.33,
402,
2),
-
-> # 以下是运营部
-
-> (
'张野',
'male',
28,
'20160311',
'operation',
10000.13,
403,
3),
-
-> (
'程咬金',
'male',
18,
'19970312',
'operation',
20000,
403,
3),
-
-> (
'程咬银',
'female',
18,
'20130311',
'operation',
19000,
403,
3),
-
-> (
'程咬铜',
'male',
18,
'20150411',
'operation',
18000,
403,
3),
-
-> (
'程咬铁',
'female',
18,
'20140512',
'operation',
17000,
403,
3)
-
-> ;
where 约束
where子句中可以使用:
- 比较运算符:> < >= <= <> !=
- between 80 and 100 # 值在80到100之间
- in(80, 90, 100) # 值是80或90或100
- like 'z%' 或 like 'zy_' # %表示任意多字符,_表示任意一个字符
- and or not # 逻辑运算符,在多个条件可以直接使用逻辑运算符
实测:
-
# 单条件查询
-
mysql>
select
id,
name
from employee
where
id <
5;
-
+
----+---------+
-
| id | name |
-
+
----+---------+
-
| 1 | egon |
-
| 2 | alex |
-
| 3 | wupeiqi |
-
| 4 | yuanhao |
-
+
----+---------+
-
4 rows in
set (
0.00 sec)
-
-
# 多条件查询
-
mysql>
select
name
from employee
where post=
'teacher'
and salary>
10000;
-
+
--------+
-
| name |
-
+
--------+
-
| alex |
-
| jinxin |
-
+
--------+
-
2 rows in
set (
0.00 sec)
-
-
# 关键字
between
and
-
mysql>
select
name,salary
from employee
where salary
between
10000
and
20000;
-
+
-----------+----------+
-
| name | salary |
-
+
-----------+----------+
-
| xiaomage | 10000.00 |
-
| 张野 | 10000.13 |
-
| 程咬金 | 20000.00 |
-
| 程咬银 | 19000.00 |
-
| 程咬铜 | 18000.00 |
-
| 程咬铁 | 17000.00 |
-
+
-----------+----------+
-
6 rows in
set (
0.00 sec)
-
-
-
# 注意:
''是空字符串,不是
null
-
mysql>
select
name,post_comment
from employee
where post_comment=
'';
-
Empty
set (
0.00 sec)
-
-
# 执行如下代码后再此查询
-
mysql>
update employee
set post_comment=
''
where
id=
2;
-
Query OK, 1 row affected (0.01 sec)
-
Rows matched: 1 Changed: 1 Warnings: 0
-
-
mysql>
select
name,post_comment
from employee
where post_comment=
'';
-
+
------+--------------+
-
| name | post_comment |
-
+
------+--------------+
-
| alex | |
-
+
------+--------------+
-
1 row in
set (
0.00 sec)
-
-
-
# 关键字
in:集合查询
-
mysql>
select
name,salary
from employee
where salary=
3000
or salary=
3500
or salary=
4000
or salary=
9000;
-
+
------------+---------+
-
| name | salary |
-
+
------------+---------+
-
| yuanhao | 3500.00 |
-
| jingliyang | 9000.00 |
-
+
------------+---------+
-
2 rows in
set (
0.00 sec)
-
-
mysql>
select
name, salary
from employee
where salary
in(
3000,
3500,
4000,
9000);
-
+
------------+---------+
-
| name | salary |
-
+
------------+---------+
-
| yuanhao | 3500.00 |
-
| jingliyang | 9000.00 |
-
+
------------+---------+
-
2 rows in
set (
0.00 sec)
-
-
mysql>
select
name,salary,post
from employee
where post=
'operation'
and (salary
not
in(
10000.13));
-
+
-----------+----------+-----------+
-
| name | salary | post |
-
+
-----------+----------+-----------+
-
| 程咬金 | 20000.00 | operation |
-
| 程咬银 | 19000.00 | operation |
-
| 程咬铜 | 18000.00 | operation |
-
| 程咬铁 | 17000.00 | operation |
-
+
-----------+----------+-----------+
-
4 rows in
set (
0.00 sec)
-
-
-
# 关键字
link:模糊查询
-
# 通配符
"%":任意多字符
-
mysql>
select *
from employee
where
name
like
'程咬%';
-
+
----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
-
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
-
+
----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
-
| 15 | 程咬金 | male | 18 | 1997-03-12 | operation | NULL | 20000.00 | 403 | 3 |
-
| 16 | 程咬银 | female | 18 | 2013-03-11 | operation | NULL | 19000.00 | 403 | 3 |
-
| 17 | 程咬铜 | male | 18 | 2015-04-11 | operation | NULL | 18000.00 | 403 | 3 |
-
| 18 | 程咬铁 | female | 18 | 2014-05-12 | operation | NULL | 17000.00 | 403 | 3 |
-
+
----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
-
4 rows in
set (
0.01 sec)
-
-
# 通配符
"_":任意单字符
-
mysql>
select *
from employee
where
name
like
'ale_';
-
+
----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
-
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
-
+
----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
-
| 2 | alex | male | 78 | 2015-03-02 | teacher | | 1000000.31 | 401 | 1 |
-
+
----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
-
1 row in
set (
0.00 sec)
-
-
-
# 其它查询
-
1.查看岗位描述不为
NULL的员工信息
-
select *
from employee
where post_comment
is
not
null;
-
-
2. 查看岗位是teacher且薪资不是10000或9000或30000的员工姓名、年龄、薪资
-
select
name,age,salary
from employee
where post=
'teacher'
and salary
not
in(
10000,
9000,
30000);
-
-
3. 查看岗位是teacher且名字是jin开头的员工姓名、年薪
-
select
name,salary*
12
from employee
where post=
'teacher'
and
name
like
'jin%';
group by 分组查询
1. 首先声明一点:分组发生在where之后,即分组是基于where之后得到的记录而进行的.
2. 分组:将所有记录按照某个相同字段进行归类,比如针对员工信息表的职位分组,或者按照性别分组等.
3. 为何要分组呢?
取每个部门的最高工资
取每个部门的员工数
取男人数和女人数小窍门:"每" 这个后面的字段,就是我们分组的依据
4. 大前提
可以按照任意字段分组,但是分组完毕后,比如group by post,只能查看post字段,如果想查看组内信息,需要借助于聚合函数.
-
# 需要设置查询模式:only_full_group_by,如果没有设置,查询的结果默认是组内的第一条记录,没有任何意义
-
-
# 如果想分组,必须要设置全局的sql的模式为ONLY_FULL_GROUP_BY
-
mysql>
set
global sql_mode=
'ONLY_FULL_GROUP_BY';
-
Query OK, 0 rows affected (0.00 sec)
-
-
# 查看MySQL 5.7默认的sql_mode如下:
-
mysql>
select @@global.sql_mode;
-
+
--------------------+
-
| @@global.sql_mode |
-
+
--------------------+
-
| ONLY_FULL_GROUP_BY |
-
+
--------------------+
-
1 row in
set (
0.00 sec)
-
-
# 设置成功后,一定要退出,然后重新登录方可生效
-
mysql>
exit;
-
Bye
-
# 简单示例:根据部门进行分组查询:
-
mysql>
select post
from employee
group
by post;
-
+
-----------------------------------------+
-
| post |
-
+
-----------------------------------------+
-
| operation |
-
| sale |
-
| teacher |
-
| 老男孩驻沙河办事处外交大使 |
-
+
-----------------------------------------+
-
4 rows in
set (
0.00 sec)
group by分组之后,只能查看当前字段,如果想查看组内信息,需要借助于聚合函数.
聚合函数
- max() # 求最大值
- min() # 求最小值
- avg() # 求平均值
- sum() # 求和
- count() # 求总个数
- group_concat(字段名) # 拼接
强调:聚合函数聚合的是组的内容,若是没有分组,则默认一组.
-
# 查每个部门有多少个员工
-
select post,
count(
1)
from employee
group
by post; # count(1):"1"的课换成"*"或字段名,好像是新版本上"1"跟"*"的速度基本无差异,
-
-
# 查每个部门的平均薪水
-
select post,
avg(salary)
from employee
group
by post;
-
-
# 查岗位名以及岗位包含的所有员工名字
-
select post,
group_concat(
name)
as
name
from employee
group
by post; # as name:重命名显示的字段名
-
-
# 查公司内男员工和女员工的个数
-
select sex,
count(
id)
from employee
group
by sex;
-
-
# 查岗位名以及各岗位的最高薪资
-
select post,
max(salary)
from employee
group
by post;
-
-
# 查男员工与男员工的平均薪资,女员工与女员工的平均薪资
-
select sex,
avg(salary)
from employee
group
by sex;
having 过滤
- 执行优先级从高到低:where > group by > having
- where发生在分组group by之前,因而where中可以有任意字段,但是绝对不能使用聚合函数
- having发生在分组group by之后,因而having中可以使用分组的字段,无法直接取到其它字段,可使用聚合函数
-
mysql>
select *
from employee
having salary>
100000; # 可能老版本不能直接使用此语法
-
+
----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
-
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
-
+
----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
-
| 2 | alex | male | 78 | 2015-03-02 | teacher | NULL | 1000000.31 | 401 | 1 |
-
+
----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
-
1 row in
set (
0.04 sec)
-
-
# 住:必须使用
group
by才能使用
group_concat()函数
-
# 错误,分组后无法直接取到组外的字段
-
mysql>
select post,
group_concat(
name)
from employee
group
by post
having salary >
1000000;
-
ERROR 1054 (42S22): Unknown column 'salary' in 'having clause'
-
# 示例
-
-
1. 查询各岗位内包含的员工个数小于
2的岗位名、岗位内包含员工名字、个数
-
select post,group_concat(name),count(
1)
from employee group by post having count(id)<2;
-
-
2. 查询各岗位平均薪资大于
10000的岗位名、平均工资
-
select post,avg(salary)
from employee group by post having avg(salary)>10000;
-
-
3. 查询各岗位平均薪资大于
10000且小于
20000的岗位名、平均工资
-
select post,avg(salary)
from employee group by post having avg(salary)>10000 and avg(salary)<20000;
order by 查询排序
按单列排序:
- select * from employee order by age; # 默认升序,根据age升序
- select * from employee order by age asc; # asc 升序
- select * from employee order by age desc; # desc 降序
按多列排序:
示例:先按照age升序排序,如果年纪相同,则按照id降序
select * from employee order by age asc, id desc;
limit 限制查询的记录数
-
# 示例
-
-
1. 查询前三行记录
-
select *
from employee
limit
3;
-
-
2. 从第0开始,即先查询出第一条,然后包含这一条在内往后查5条
-
select *
from employee
order
by salary
desc
limit
0,
5;
-
-
3. 从第5开始,即先查询出第6条,然后包含这一条在内往后查5条
-
select *
from employee
order
by salary
desc
limit
5,
5;
-
-
-
4. 从偏移5开始,往后取10条数据
-
limit 10 offset 5
"