文章目录
- 一、单表查询的语法及关键字执行的优先级
- 二、简单查询
- 三、约束条件(where)
- 四、分组(group by)
- 五、聚合函数
- 六、过滤(having)
- 七、查询排序(order by)
- 八、限制查询的记录数(limit)
- 九、使用正则表达式查询
一、单表查询的语法及关键字执行的优先级
1.1 单表查询语法
SELECT DISTINCT 字段1,字段2... FROM 表名
WHERE 条件
GROUP BY field
HAVING 筛选
ORDER BY field
LIMIT 限制条数
1.2 关键字执行的优先级
- from:找到表
- where:拿着where指定的约束条件,去文件/表中取出一条条记录
- group by:将取出的一条条记录进行分组group by,如果没有group by,则整体作为一组
- select:执行select
- distinct:去重
- having:将分组的结果进行having过滤
- order by:将结果按条件排序:order by
- limit:限制结果的显示条数
1.3 数据建表准备
company.employee
员工id id int
姓名 emp_name varchar
性别 sex enum
年龄 age int
入职日期 hire_date date
岗位 post varchar
职位描述 post_comment varchar
薪水 salary double
办公室 office int
部门编号 depart_id int
# 创建表
create table employee(
id int not null unique auto_increment,
emp_name varchar(20) not null,
gender 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
);
# 查看表结构
desc employee;
+--------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| emp_name | varchar(20) | NO | | NULL | |
| gender | 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 | |
+--------------+-----------------------+------+-----+---------+----------------+
# 插入记录
# 三个部门:教学--部门 1 ,销售--部门 2,运营--部门 3
insert into employee(emp_name,gender,age,hire_date,post,salary,office,depart_id) values
('nick','male',18,'20170301','老男孩驻上海虹桥最帅',7300.33,401,1),
('jason','male',78,'20150302','teacher',1000000.31,401,1),
('sean','male',81,'20130305','teacher',8300,401,1),
('tank','male',73,'20140701','teacher',3500,401,1),
('oscar','male',28,'20121101','teacher',2100,401,1),
('mac','female',18,'20110211','teacher',9000,401,1),
('rocky','male',18,'19000301','teacher',30000,401,1),
('成龙','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)
;
二、简单查询
2.1 去重distinct`
select post from employee;
+--------------------------------+
| post |
+--------------------------------+
| 老男孩驻上海虹桥最帅 |
| teacher |
| teacher |
| teacher |
| teacher |
| teacher |
| teacher |
| teacher |
| sale |
| sale |
| sale |
| sale |
| sale |
| operation |
| operation |
| operation |
| operation |
| operation |
+--------------------------------+
select distinct post from employee;
+--------------------------------+
| post |
+--------------------------------+
| 老男孩驻上海虹桥最帅 |
| teacher |
| sale |
| operation |
+--------------------------------+
2.2 通过四则运算查询
select emp_name,salary from employee;
+-----------+------------+
| emp_name | salary |
+-----------+------------+
| nick | 7300.33 |
| jason | 1000000.31 |
| sean | 8300.00 |
| tank | 3500.00 |
| oscar | 2100.00 |
| mac | 9000.00 |
| rocky | 30000.00 |
| 成龙 | 10000.00 |
| 歪歪 | 3000.13 |
| 丫丫 | 2000.35 |
| 丁丁 | 1000.37 |
| 星星 | 3000.29 |
| 格格 | 4000.33 |
| 张野 | 10000.13 |
| 程咬金 | 20000.00 |
| 程咬银 | 19000.00 |
| 程咬铜 | 18000.00 |
| 程咬铁 | 17000.00 |
+-----------+------------+
select emp_name,salary*12 from employee;
+-----------+-------------+
| emp_name | salary*12 |
+-----------+-------------+
| nick | 87603.96 |
| jason | 12000003.72 |
| sean | 99600.00 |
| tank | 42000.00 |
| oscar | 25200.00 |
| mac | 108000.00 |
| rocky | 360000.00 |
| 成龙 | 120000.00 |
| 歪歪 | 36001.56 |
| 丫丫 | 24004.20 |
| 丁丁 | 12004.44 |
| 星星 | 36003.48 |
| 格格 | 48003.96 |
| 张野 | 120001.56 |
| 程咬金 | 240000.00 |
| 程咬银 | 228000.00 |
| 程咬铜 | 216000.00 |
| 程咬铁 | 204000.00 |
+-----------+-------------+
select emp_name,salary*12 as Annual_salary from employee;
select emp_name,salary*12 Annual_salary from employee;
+-----------+---------------+
| emp_name | Annual_salary |
+-----------+---------------+
| nick | 87603.96 |
| jason | 12000003.72 |
| sean | 99600.00 |
| tank | 42000.00 |
| oscar | 25200.00 |
| mac | 108000.00 |
| rocky | 360000.00 |
| 成龙 | 120000.00 |
| 歪歪 | 36001.56 |
| 丫丫 | 24004.20 |
| 丁丁 | 12004.44 |
| 星星 | 36003.48 |
| 格格 | 48003.96 |
| 张野 | 120001.56 |
| 程咬金 | 240000.00 |
| 程咬银 | 228000.00 |
| 程咬铜 | 216000.00 |
| 程咬铁 | 204000.00 |
+-----------+---------------+
2.3 定义显示格式
CONCAT()
函数用于连接字符串
select concat('姓名: ',emp_name,' 年薪: ', salary*12)as Annual_salary from employee;
+--------------------------------------+
| Annual_salary |
+--------------------------------------+
| 姓名: nick 年薪: 87603.96 |
| 姓名: jason 年薪: 12000003.72 |
| 姓名: sean 年薪: 99600.00 |
| 姓名: tank 年薪: 42000.00 |
| 姓名: oscar 年薪: 25200.00 |
| 姓名: mac 年薪: 108000.00 |
| 姓名: rocky 年薪: 360000.00 |
| 姓名: 成龙 年薪: 120000.00 |
| 姓名: 歪歪 年薪: 36001.56 |
| 姓名: 丫丫 年薪: 24004.20 |
| 姓名: 丁丁 年薪: 12004.44 |
| 姓名: 星星 年薪: 36003.48 |
| 姓名: 格格 年薪: 48003.96 |
| 姓名: 张野 年薪: 120001.56 |
| 姓名: 程咬金 年薪: 240000.00 |
| 姓名: 程咬银 年薪: 228000.00 |
| 姓名: 程咬铜 年薪: 216000.00 |
| 姓名: 程咬铁 年薪: 204000.00 |
+--------------------------------------+
CONCAT_WS()
第一个参数为分隔符
select concat_ws(':',emp_name,salary*12)as Annual_salary from employee;
+---------------------+
| Annual_salary |
+---------------------+
| nick:87603.96 |
| jason:12000003.72 |
| sean:99600.00 |
| tank:42000.00 |
| oscar:25200.00 |
| mac:108000.00 |
| rocky:360000.00 |
| 成龙:120000.00 |
| 歪歪:36001.56 |
| 丫丫:24004.20 |
| 丁丁:12004.44 |
| 星星:36003.48 |
| 格格:48003.96 |
| 张野:120001.56 |
| 程咬金:240000.00 |
| 程咬银:228000.00 |
| 程咬铜:216000.00 |
| 程咬铁:204000.00 |
+---------------------+
# 作用相当于
select concat(emp_name,':',salary*12)as Annual_salary from employee;
结合CASE语句:
SELECT
(
CASE
WHEN emp_name = 'mac' THEN
emp_name
WHEN emp_name = 'jason' THEN
CONCAT(emp_name,'_BIGSB')
ELSE
concat(emp_name, 'SB')
END
) as new_name
FROM
employee;
+-------------+
| new_name |
+-------------+
| nickSB |
| jason_BIGSB |
| seanSB |
| tankSB |
| oscarSB |
| mac |
| rockySB |
| 成龙SB |
| 歪歪SB |
| 丫丫SB |
| 丁丁SB |
| 星星SB |
| 格格SB |
| 张野SB |
| 程咬金SB |
| 程咬银SB |
| 程咬铜SB |
| 程咬铁SB |
+-------------+
三、约束条件(where)
1. 单条件查询
SELECT emp_name FROM employee WHERE post='sale';
2. 多条件查询
SELECT emp_name,salary FROM employee WHERE post='teacher' AND salary>10000;
3. 关键字BETWEEN AND
SELECT emp_name,salary FROM employee WHERE salary BETWEEN 10000 AND 20000;
+-----------+----------+
| emp_name | salary |
+-----------+----------+
| 成龙 | 10000.00 |
| 张野 | 10000.13 |
| 程咬金 | 20000.00 |
| 程咬银 | 19000.00 |
| 程咬铜 | 18000.00 |
| 程咬铁 | 17000.00 |
+-----------+----------+
SELECT emp_name,salary FROM employee WHERE salary NOT BETWEEN 10000 AND 20000;
+----------+------------+
| emp_name | salary |
+----------+------------+
| nick | 7300.33 |
| jason | 1000000.31 |
| sean | 8300.00 |
| tank | 3500.00 |
| oscar | 2100.00 |
| mac | 9000.00 |
| rocky | 30000.00 |
| 歪歪 | 3000.13 |
| 丫丫 | 2000.35 |
| 丁丁 | 1000.37 |
| 星星 | 3000.29 |
| 格格 | 4000.33 |
+----------+------------+
4. 关键字IS NULL(判断某个字段是否为NULL不能用等号,需要用IS)
SELECT emp_name,post_comment FROM employee WHERE post_comment IS NULL;
SELECT emp_name,post_comment FROM employee WHERE post_comment IS NOT NULL;
SELECT emp_name,post_comment FROM employee WHERE post_comment=''; 注意''是空字符串,不是null
ps:
执行
update employee set post_comment='' where id=2;
再用上条查看,就会有结果了
5. 关键字IN集合查询
SELECT emp_name,salary FROM employee WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ;
+----------+---------+
| emp_name | salary |
+----------+---------+
| tank | 3500.00 |
| mac | 9000.00 |
+----------+---------+
SELECT emp_name,salary FROM employee WHERE salary IN (3000,3500,4000,9000) ;
+----------+---------+
| emp_name | salary |
+----------+---------+
| tank | 3500.00 |
| mac | 9000.00 |
+----------+---------+
SELECT emp_name,salary FROM employee WHERE salary NOT IN (3000,3500,4000,9000) ;
+-----------+------------+
| emp_name | salary |
+-----------+------------+
| nick | 7300.33 |
| jason | 1000000.31 |
| sean | 8300.00 |
| oscar | 2100.00 |
| rocky | 30000.00 |
| 成龙 | 10000.00 |
| 歪歪 | 3000.13 |
| 丫丫 | 2000.35 |
| 丁丁 | 1000.37 |
| 星星 | 3000.29 |
| 格格 | 4000.33 |
| 张野 | 10000.13 |
| 程咬金 | 20000.00 |
| 程咬银 | 19000.00 |
| 程咬铜 | 18000.00 |
| 程咬铁 | 17000.00 |
+-----------+------------+
6. 关键字LIKE模糊查询
通配符’%’
SELECT * FROM employee WHERE emp_name LIKE 'ni%';
+----+----------+--------+-----+------------+--------------------------------+--------------+--------
| id | emp_name | gender | age | hire_date | post | post_comment | salary | office | depart_id |
+----+----------+--------+-----+------------+--------------------------------+--------------+--------
| 1 | nick | male | 18 | 2017-03-01 | 老男孩驻上海虹桥最帅| NULL| 7300.33 | 401 | 1 |
+----+----------+--------+-----+------------+--------------------------------+--------------+--------
SELECT * FROM employee WHERE emp_name LIKE 'ja__';
Empty set (0.00 sec)
SELECT * FROM employee WHERE emp_name LIKE 'jason';
+----+----------+--------+-----+------------+---------+--------------+------------+--------+---------
| id | emp_name | gender | age | hire_date | post | post_comment | salary | office |depart_id |
+----+----------+--------+-----+------------+---------+--------------+------------+--------+---------
| 2 | jason | male | 78 | 2015-03-02 | teacher | NULL |1000000.31| 401 | 1 |
+----+----------+--------+-----+------------+---------+--------------+------------+--------+---------
select emp_name from employee where emp_name like '%o%';
+----------+
| emp_name |
+----------+
| jason |
| oscar |
| rocky |
+----------+
3.1 练习
- 查看岗位是teacher的员工姓名、年龄
- 查看岗位是teacher且年龄大于30岁的员工姓名、年龄
- 查看岗位是teacher且薪资在9000-1000范围内的员工姓名、年龄、薪资
- 查看岗位描述不为NULL的员工信息
- 查看岗位是teacher且薪资是10000或9000或30000的员工姓名、年龄、薪资
- 查看岗位是teacher且薪资不是10000或9000或30000的员工姓名、年龄、薪资
- 查看岗位是teacher且名字是mac开头的员工姓名、年薪
select emp_name,age from employee where post = 'teacher';
select emp_name,age from employee where post='teacher' and age > 30;
select emp_name,age,salary from employee where post='teacher' and salary between 9000 and 10000;
select * from employee where post_comment is not null;
select emp_name,age,salary from employee where post='teacher' and salary in (10000,9000,30000);
select emp_name,age,salary from employee where post='teacher' and salary not in (10000,9000,30000);
select emp_name,salary*12 from employee where post='teacher' and emp_name like 'mac%';
四、分组(group by)
分组:就是将单个的个体按照一定的规则分成一个整体(例如:按照性别分成男女两组…)
分组之后默认只能直接获取到分组的依据, 分组后也就是默认以组进行操作,而不是单个的记录
SELECT post FROM employee GROUP BY post;
+--------------------------------+
| post |
+--------------------------------+
| 老男孩驻上海虹桥最帅 |
| teacher |
| sale |
| operation |
+--------------------------------+
select * from employee group by post;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'company.employee.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
select post,id from employee group by post;
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'company.employee.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
group_concat()
字段
SELECT post,GROUP_CONCAT(emp_name) FROM employee GROUP BY post; # 按照岗位分组,并查看组内成员名
+--------------------------------+------------------------------------------------+
| post | GROUP_CONCAT(emp_name) |
+--------------------------------+------------------------------------------------+
| operation | 张野,程咬金,程咬银,程咬铜,程咬铁 |
| sale | 歪歪,丫丫,丁丁,星星,格格 |
| teacher | jason,sean,tank,oscar,mac,rocky,成龙 |
| 老男孩驻上海虹桥最帅 | nick |
+--------------------------------+------------------------------------------------+
select post,group_concat(emp_name,salary) from employee group by post;
+------------------+-------------------------------------------------------------------
| post | group_concat(emp_name,salary)
+------------------+-------------------------------------------------------------------
| operation | 张野10000.13,程咬金20000.00,程咬银19000.00,程咬铜18000.00,程咬铁 17000.00
| sale | 歪歪3000.13,丫丫2000.35,丁丁1000.37,星星3000.29,格格4000.33
| teacher | jason1000000.31,sean8300.00,tank3500.00,oscar2100.00,mac9000.00,rocky30000.00,成龙10000.00
| 老男孩驻上海虹桥最帅 | nick7300.33
+-------------------+-------------------------------------------------------------------
与聚合函数一起使用
select post,count(id) as count from employee group by post; # 按照岗位分组,并查看每个组有多少人
+--------------------------------+-------+
| post | count |
+--------------------------------+-------+
| 老男孩驻上海虹桥最帅 | 1 |
| teacher | 7 |
| sale | 5 |
| operation | 5 |
+--------------------------------+-------+
注意:如果我们用unique的字段作为分组的依据,则每一条记录自成一组,这种分组没有意义;多条记录之间的某个字段值相同,该字段通常用来作为分组的依据。
五、聚合函数
强调:聚合函数聚合的是组的内容,若是没有分组,则默认一组。
SELECT COUNT(*) FROM employee;
SELECT COUNT(*) FROM employee WHERE depart_id=1;
SELECT MAX(salary) FROM employee;
SELECT MIN(salary) FROM employee;
SELECT AVG(salary) FROM employee;
SELECT SUM(salary) FROM employee;
SELECT SUM(salary) FROM employee WHERE depart_id=3;
5.1 练习
-
查询岗位名以及岗位包含的所有员工名字
select post,group_concat(emp_name) from employee group by post; +--------------------------------+------------------------------------------------+ | post | GROUP_CONCAT(emp_name) | +--------------------------------+------------------------------------------------+ | operation | 张野,程咬金,程咬银,程咬铜,程咬铁 | | sale | 歪歪,丫丫,丁丁,星星,格格 | | teacher | jason,sean,tank,oscar,mac,rocky,成龙 | | 老男孩驻上海虹桥最帅 | nick | +--------------------------------+------------------------------------------------+
-
查询岗位名以及各岗位内包含的员工个数
select post,count(emp_name) from employee group by post; +--------------------------------+-----------------+ | post | count(emp_name) | +--------------------------------+-----------------+ | 老男孩驻上海虹桥最帅 | 1 | | teacher | 7 | | sale | 5 | | operation | 5 | +--------------------------------+-----------------+
-
查询公司内男员工和女员工的个数
select gender,count(id) as'员工个数' from employee group by gender; +--------+--------------+ | gender | 员工个数 | +--------+--------------+ | male | 10 | | female | 8 | +--------+--------------+
-
查询岗位名以及各岗位的平均薪资
select post,avg(salary)as'平均薪资' from employee group by post; +--------------------------------+---------------+ | post | 平均薪资 | +--------------------------------+---------------+ | 老男孩驻上海虹桥最帅 | 7300.330000 | | teacher | 151842.901429 | | sale | 2600.294000 | | operation | 16800.026000 | +--------------------------------+---------------+
-
查询岗位名以及各岗位的最高薪资
select post,max(salary)as'最高薪资' from employee group by post; +--------------------------------+--------------+ | post | 最高薪资 | +--------------------------------+--------------+ | 老男孩驻上海虹桥最帅 | 7300.33 | | teacher | 1000000.31 | | sale | 4000.33 | | operation | 20000.00 | +--------------------------------+--------------+
-
查询男员工与男员工的平均薪资,女员工与女员工的平均薪资
select gender,avg(salary) as '平均薪资' from employee group by gender;
+--------+---------------+
| gender | 平均薪资 |
+--------+---------------+
| male | 110920.077000 |
| female | 7250.183750 |
+--------+---------------+
六、过滤(having)
6.1 where和having的区别
执行优先级从高到低:where > group by > having
- Where 发生在分组group by之前,因而Where中可以有任意字段,但是绝对不能使用聚合函数。
- Having发生在分组group by之后,因而Having中可以使用分组的字段,无法直接取到其他字段,可以使用聚合函数
6.2 练习
-
查询各岗位内包含的员工个数小于2的岗位名、岗位内包含员工名字、个数
select post,group_concat(emp_name) as '员工名',count(id) as '员工个数' from employee group by post having count(id)<2; +--------------------------------+-----------+--------------+ | post | 员工名 | 员工个数 | +--------------------------------+-----------+--------------+ | 老男孩驻上海虹桥最帅 | nick | 1 | +--------------------------------+-----------+--------------+
-
查询各岗位平均薪资大于10000的岗位名、平均工资
select post,avg(salary) as '平均工资' from employee group by post having avg(salary)>10000; +-----------+---------------+ | post | 平均工资 | +-----------+---------------+ | teacher | 151842.901429 | | operation | 16800.026000 | +-----------+---------------+
-
查询各岗位平均薪资大于10000且小于20000的岗位名、平均工资
select post,avg(salary) as '平均工资' from employee group by post having avg(salary) > 10000 and avg(salary) <20000; +-----------+--------------+ | post | 平均工资 | +-----------+--------------+ | operation | 16800.026000 | +-----------+--------------+
七、查询排序(order by)
SELECT * FROM employee ORDER BY salary;
SELECT * FROM employee ORDER BY salary ASC; # 升序
SELECT * FROM employee ORDER BY salary DESC; # 降序
按多列排序:先按照age排序,如果年纪相同,则按照薪资排序
SELECT * from employee ORDER BY age, salary DESC;
7.1 练习
-
查询所有员工信息,先按照age升序排序,如果age相同则按照hire_date降序排序
select * from employee order by age asc, hire_date desc;
-
查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资升序排列
select post,avg(salary) from employee group by post having avg(salary) > 10000 order by avg(salary) asc; +-----------+---------------+ | post | avg(salary) | +-----------+---------------+ | operation | 16800.026000 | | teacher | 151842.901429 | +-----------+---------------+
八、限制查询的记录数(limit)
SELECT * FROM employee ORDER BY salary DESC
LIMIT 3; #默认初始位置为0
SELECT * FROM employee ORDER BY salary DESC
LIMIT 2,5; #从第2开始,即先出第3条,然后包含这一条在内往后查5条
SELECT * FROM employee ORDER BY salary DESC
LIMIT 5,5; #从第5开始,即先出第6条,然后包含这一条在内往后查5条
8.1 练习
- 薪资最高的与员工的所有信息
select * from employee order by salary desc limit 1;
+----+----------+--------+-----+------------+--------+--------------+------------+--------+---------
| id | emp_name | gender | age | hire_date | post | post_comment | salary | office | depart_id
+----+----------+--------+-----+------------+--------+--------------+------------+--------+---------
| 2 | jason | male | 78 | 2015-03-02 | teacher| NULL | 1000000.31 | 401 | 1
+----+----------+--------+-----+------------+--------+--------------+------------+--------+---------
九、使用正则表达式查询
SELECT * FROM employee WHERE emp_name REGEXP '^jas';
SELECT * FROM employee WHERE emp_name REGEXP 'on$';
SELECT * FROM employee WHERE emp_name REGEXP 'm{2}';
小结:对字符串匹配的方式
WHERE emp_name = 'nick';
WHERE emp_name LIKE 'sea%';
WHERE emp_name REGEXP 'on$';
9.1 练习
- 查看所有员工中名字是mac开头,n或者g结果的员工信息
select * from employee where emp_name regexp '^mac.*[gn]$';