【MySQL】单表查询

我们两清 提交于 2019-11-28 07:53:02

原文: http://blog.gqylpy.com/gqy/251

目录

where 约束

group by 分组查询

聚合函数

having 过滤

order by 查询排序

limit 限制查询的记录数


# 语法select 字段1, 字段2 ... from 表名    where 条件    group by field    having 筛选    order by field    limit 限制条数

重点在于关键字的执行优先级:
from
where
group by
having
select
distinct
order by
limit

1. 找到表: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子句中可以使用:

  1. 比较运算符:>  <  >=  <=  <>  !=
  2. between 80 and 100        # 值在80到100之间
  3. in(80, 90, 100)        # 值是80或90或100
  4. like 'z%' 或 like 'zy_'        # %表示任意多字符,_表示任意一个字符
  5. 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 andmysql> 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)  # 注意:''是空字符串,不是nullmysql> 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_BYmysql> 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 过滤

  1. 执行优先级从高到低:where > group by > having
  2. where发生在分组group by之前,因而where中可以有任意字段,但是绝对不能使用聚合函数
  3. 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

 

 



 

原文: http://blog.gqylpy.com/gqy/251

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!