准备表和记录
# 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 emp(
id int not null unique 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
);
# 插入记录
insert into emp(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),
('成龙','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)
;
INSERT 增加
INSERT INTO 表名(字段1,字段2,字段3…字段n) VALUES(值1,值2,值3…值n);
INSERT INTO 表名 VALUES (值1,值2,值3…值n);
# 插入多条记录
INSERT INTO 表名 VALUES
(值1,值2,值3…值n),
(值1,值2,值3…值n),
(值1,值2,值3…值n);
# 插入查询结果
INSERT INTO 表名(字段1,字段2,字段3…字段n)
SELECT (字段1,字段2,字段3…字段n) FROM 表2;
UPDATE 修改
UPDATE 表名 SET
字段1=值1,
字段2=值2 WHERE 条件;
UPDATE mysql.user SET password=password(‘123’)
where user=’root’ and host=’localhost’;
DELETE 删除
DELETE FROM 表名
WHERE CONITION;
DELETE FROM mysql.user
WHERE password=’’;
单表数据查询
建数据库的目的是保存数据和随时查询数据,且查询数据占大部分.
最基本语法: select * from t_name;
SELECT 字段1,字段2... FROM 表名
WHERE 条件
GROUP BY field
HAVING 筛选
ORDER BY field
LIMIT 限制条数
条件:由上到下按顺序执行,没有就跳过
|条件|作用|
|:--:|:--:|
|where
|约束条件,首先取出符合条件的记录|
|group by
| 分组,若没有指定,则理解为按照id分组,分组字段可以利用聚合函数|
|having
| 过滤,与group by成对出现|
|distinct
| 去重|
|order by
| 排序|
|limit
| 显示条数|
WHERE
根据条件筛选记录.
绝对匹配: =
,!=
;
模糊匹配:
比较运算符:>
, <
, >=
, <=
;
between 80 and 100
值在80
到100
之间;
in(80,90,100)
值是10
或20
或30
;
like 'egon%'
:pattern
可以是%
或_
, %
表示任意多字符, _
表示一个字符;
逻辑运算符:在多个条件直接可以使用逻辑运算符 and
, or
, not
;
# 单条件查询
SELECT name FROM employee WHERE post='sale';
# 多条件查询
SELECT name,salary FROM employee
WHERE post='teacher' AND salary>10000;
# BETWEEN num1 AND num2
SELECT name,salary FROM employee
WHERE salary BETWEEN 10000 AND 20000;
SELECT name,salary FROM employee
WHERE salary NOT BETWEEN 10000 AND 20000;
# 判断字段< 10000或者> 20000
# IS NULL: 判断某个字段是否为NULL不能用等号,需要用is
SELECT name,post_comment FROM employee
WHERE post_comment IS NULL;
SELECT name,post_comment FROM employee
WHERE post_comment IS NOT NULL;
SELECT name,post_comment FROM employee
WHERE post_comment='';
# 注意''是空字符串,不是null
# or, in: 集合查询
SELECT name,salary FROM employee
WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ;
SELECT name,salary FROM employee
WHERE salary IN (3000,3500,4000,9000) ;
SELECT name,salary FROM employee
WHERE salary NOT IN (3000,3500,4000,9000) ;
# like: 模糊查询
通配符 '%'
SELECT * FROM employee
WHERE name LIKE 'eg%';
通配符'_'
SELECT * FROM employee
WHERE name LIKE 'al__';
# 正则表达式查询
SELECT * FROM employee WHERE name REGEXP '^ale';
SELECT * FROM employee WHERE name REGEXP 'on$';
SELECT * FROM employee WHERE name REGEXP 'm{2}';
# 练习
查看所有员工中名字是jin开头,n或者g结果的员工信息
select * from emp where name regexp "^jin.*[ng]$";
# 练习
1. 查看岗位是teacher的员工姓名、年龄;
select name, age from employee where post='teacher';
2. 查看岗位是teacher且年龄大于30岁的员工姓名、年龄;
select name, age from employee where post='teacher' and age>30;
3. 查看岗位是teacher且薪资在9000-10000范围内的员工姓名、年龄、薪资;
select name, age, salary from employee
where post='teacher' and salary between 9000 and 10000;
4. 查看岗位描述不为NULL的员工信息;
select id, post from employee where post_comment is not null;
5. 查看岗位是teacher且薪资是10000或9000或30000的员工姓名、年龄、薪资;
select name, age, salary from employee
where post='teacher' and salary in (10000,9000,30000);
6. 查看岗位是teacher且薪资不是10000或9000或30000的员工姓名、年龄、薪资;
select name, age, salary from employee
where post='teacher' and salary not in (10000,9000,30000);
7. 查看岗位是teacher且名字是jin开头的员工姓名、年薪;
select name,salary*12 as annual_salary from employee
where post='teacher' and name like 'jin%';
GROUP BY
以某个字段作为分组,若没有指定,则理解为以id为一组.
# GROUP BY: 单独使用
SELECT post FROM employee GROUP BY post;
# GROUP BY & GROUP_CONCAT() 组合使用
# 按照岗位分组,并连接组内成员姓名
SELECT post,GROUP_CONCAT(name) as emp_members FROM employee GROUP BY post;
# GROUP BY & 聚合函数 组合使用
# 按照岗位分组,并查看每个组有多少人
select post,count(id) as count from employee group by post;
# 求每个分类的记录个数
select depart_id,count(name) from employee group by depart_id;
+-----------+-------------+
| depart_id | count(name) |
+-----------+-------------+
| 1 | 8 |
| 2 | 5 |
| 3 | 5 |
+-----------+-------------+
3 rows in set (0.00 sec)
# 将符合类别的所有记录的名字组合成一项
select depart_id, group_concat(name) from employee
group by depart_id;
# 求每个部门中的工资的最大值
select depart_id, max(salary) from employee group by depart_id;
+-----------+-------------+
| depart_id | max(salary) |
+-----------+-------------+
| 1 | 1000000.31 |
| 2 | 3000.29 |
| 3 | 20000.00 |
+-----------+-------------+
3 rows in set (0.00 sec)
聚合函数:
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;
# 练习
1. 查询 岗位名 以及 岗位包含的所有员工名字
select post, group_concat(name) from emp group by post;
2. 查询岗位名以及各岗位内包含的员工个数
select post, count(id) from emp group by post;
3. 查询公司内男员工和女员工的个数
select sex, count(id) from emp group by sex;
4. 查询岗位名以及各岗位的平均薪资
select post, avg(salary) as '平均薪资' from emp group by post;
5. 查询岗位名以及各岗位的最高薪资
select post, max(salary) as '最高薪资' from emp group by post;
6. 查询岗位名以及各岗位的最低薪资
select post, max(salary) as '最低薪资' from emp group by post;
7. 查询男员工与男员工的平均薪资,女员工与女员工的平均薪资
select sex, avg(salary) as '平均薪资' from emp group by sex;
HAVING
与group by成对出现.
# 1. 查询各岗位内包含的员工个数小于2的岗位名、岗位内包含员工名字、个数
select post, group_concat(name) as emp_names, count(id) as emp_num from employee group by post having emp_num <2;
# 3. 查询每个岗位 平均薪资大于10000 的岗位名、平均工资
select post, avg(salary) as avg_salary from employee
group by post having avg_salary>10000;
# 4. 查询每个岗位 平均薪资大于10000 且 小于20000的岗位名、平均工资
select post, avg(salary) from emp group by post
having avg(salary) in (10000, 20000) ;
ORDER BY
排序,默认升序排列asc;降序desc.
# 单列排序, 默认升序
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;
# 练习
1. 查询所有员工信息,先按照age升序排序,如果age相同则按照hire_date降序排序:
select * from employee order by age, hire_date desc;
2. 查询每个岗位 平均薪资 大于10000 的 岗位名、平均工资, 结果按平均薪资升序排列:
select post, avg(salary) as post_avg from employee
group by post having post_avg>10000 order by post_avg;
limit
限定查询结果记录的条数.索引默认从0
开始,limit 0, 2
: 从索引0
开始, 然后长度是2
;
SELECT * FROM employee ORDER BY salary DESC
LIMIT 3;
SELECT * FROM employee ORDER BY salary DESC
LIMIT 0,5;
SELECT * FROM employee ORDER BY salary DESC
LIMIT 5,5;
# 练习
1. 分页显示,每页5条
select * from emp limit 5;
select * from emp limit 5, 5;
select * from emp limit 10, 5;
多表连接查询
准备表
# 部门表
create table dept(
id int primary key not null auto_increment,
name varchar(20) not null
);
# 员工信息表
create table employee(
id int primary key auto_increment,
name varchar(20) not null,
sex enum('male','female') not null default 'male',
age int not null ,
dept_id int not null,
foreign key(dept_id) references dept(id)
on delete cascade
on update cascade
);
# 插入数据
insert into dept(name) values
('技术'),
('人力资源'),
('销售'),
('运营');
insert into employee(name,sex,age,dept_id) values
('kate','male',18,1),
('alex','female',48,2),
('bob','male',38,3),
('shanshan','female',28,4),
('jim','male',18,1),
('dereck','female',18,3)
;
连表查询
innerjoin:内连接,只显示共有部分,利用on关键字连接两个表.
# 常规方法
select employee.id,employee.name,employee.age,employee.sex,department.name
from employee,department where employee.dep_id=department.id;
# inner join,可以取出特定字段
select employee.id,employee.name,employee.age,employee.sex,dept.name
from employee inner join dept on employee.dep_id=dept.id;
+----+-----------+------+--------+--------------+
| id | name | age | sex | name |
+----+-----------+------+--------+--------------+
| 1 | egon | 18 | male | 技术 |
| 2 | alex | 48 | female | 人力资源 |
| 3 | wupeiqi | 38 | male | 人力资源 |
| 4 | yuanhao | 28 | female | 销售 |
| 5 | liwenzhou | 18 | male | 技术 |
+----+-----------+------+--------+--------------+
left join:外连接之左连接,优先显示左表全部记录,没有找到与左侧表对应的字段以NULL代替.
select employee.id,employee.name,department.name as depart_name
from employee left join department
on employee.dep_id=department.id;
+----+------------+--------------+
| id | name | depart_name |
+----+------------+--------------+
| 1 | egon | 技术 |
| 5 | liwenzhou | 技术 |
| 2 | alex | 人力资源 |
| 3 | wupeiqi | 人力资源 |
| 4 | yuanhao | 销售 |
| 6 | jingliyang | NULL |
right join:以右侧表优先,优先显示右表全部记录,没有找到与右侧表对应的字段以NULL代替.
select employee.id,employee.name,dept.name as dept_name
from employee right join dept
on employee.dept_id=dept.id;
+------+-----------+--------------+
| id | name | depart_name |
+------+-----------+--------------+
| 1 | egon | 技术 |
| 2 | alex | 人力资源 |
| 3 | wupeiqi | 人力资源 |
| 4 | yuanhao | 销售 |
| 5 | liwenzhou | 技术 |
| NULL | NULL | 运营 |
+------+-----------+--------------+
练习:以内连接的方式查询employee
和dept
表,并且employee表中的age
字段值必须大于25
,即找出年龄大于25岁的员工以及员工所在的部门.
select employee.id, employee.name as "员工", employee.age, dept.name as '部门' from employee right join dept
on employee.dept_id = dept.id
where age > 25 order by age;
+------+---------+------+----------+
| id | 员工 | age | 部门 |
+------+---------+------+----------+
| 2 | alex | 48 | 人力资源 |
| 3 | wupeiqi | 38 | 销售 |
| 4 | yuanhao | 28 | 运营 |
+------+---------+------+----------+
3 rows in set (0.00 sec)
子查询
将一个查询结果放进另外一个查询语句的查询条件中。
- 比较运算符:
=
,!=
,>
,<
.
# 查询大于 所有人 平均年龄 的 员工的姓名与年龄
mysql> select name, age from emp where age>(select avg(age) from emp);
+---------+-----+
| name | age |
+---------+-----+
| alex | 48 |
| wupeiqi | 38 |
+---------+-----+
2 rows in set (0.00 sec)
# 查询大于 部门 内平均年龄的员工姓名、年龄
# 1. 新建dept_id, avg_age的中间表;
# 2. 将其连接employee表, 筛选出age和avg_age字段;
select t1.name,t1.age from employee t1
inner join
(select dept_id,avg(age) as avg_age from employee group by dept_id) t2
on t1.dept_id = t2.dept_id
where t1.age >= t2.avg_age;
+---------+-----+
| name | age |
+---------+-----+
| alex | 48 |
| wupeiqi | 38 |
| yuanhao | 28 |
| jim1 | 29 |
| jack | 40 |
+---------+-----+
5 rows in set (0.00 sec)
- 关键字:
IN
、NOT IN
、ANY
、ALL
、EXISTS
和NOT EXISTS
;
# 查询 平均年龄 在25岁以上的 部门名
select id,name from dept
where id in
(select dept_id from emp group by dept_id
having avg(age) > 25);
# 查看 技术部 员工姓名
select name, dept_id from employee
where dept_id in
(select id from dept where name ='技术');
# 查看 不足1人 的部门名
select name from dept where id in (select dept_id as dept_num from emp group by dept_id having count(id) <=1);
+----------+
| name |
+----------+
| 人力资源 |
| 运营 |
+----------+
2 rows in set (0.00 sec)
- EXISTS:表示存在,返回
True
或False
.当返回True
时,外层查询语句将进行查询;当返回值为False
时,外层查询语句不进行查询.
# department表中存在dept_id=203,Ture
select * from employee where exists
(select id from dept where id=200);
+----+------------+--------+------+--------+
| id | name | sex | age | dep_id |
+----+------------+--------+------+--------+
| 1 | egon | male | 18 | 200 |
| 2 | alex | female | 48 | 201 |
| 3 | wupeiqi | male | 38 | 201 |
| 4 | yuanhao | female | 28 | 202 |
| 5 | liwenzhou | male | 18 | 200 |
| 6 | jingliyang | female | 18 | 204 |
+----+------------+--------+------+--------+
# department表中存在dept_id=205,False
select * from employee
where exists
(select id from department where id=204);
Empty set (0.00 sec)