mysql(7)、表操作之增删改查

准备表和记录

# 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 值在80100之间;
in(80,90,100)值是102030;
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      | 运营         |
+------+-----------+--------------+   

练习:以内连接的方式查询employeedept表,并且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)
  • 关键字INNOT INANYALLEXISTSNOT 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:表示存在,返回TrueFalse.当返回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)

猜你喜欢

转载自www.cnblogs.com/fqh202/p/9428033.html