数据库03: 表记录操作与查询

Posted fqh202

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库03: 表记录操作与查询相关的知识,希望对你有一定的参考价值。

概述

mysql管理软件中,可以通过SQL语句中的 DML语言来实现数据的操作,包括:

  1. INSERT实现数据的插入;
  2. UPDATE实现数据的更新;
  3. DELETE实现数据的删除;
  4. SELECT查询数据.

INSERT

# 插入完整数据(顺序插入)
    语法一:
    INSERT INTO 表名(字段1,字段2,字段3…字段n) VALUES(值1,值2,值3…值n);
    
    语法二:
    INSERT INTO 表名 VALUES (值1,值2,值3…值n);

# 指定字段插入数据
    语法:
    INSERT INTO 表名(字段1,字段2,字段3…) VALUES (值1,值2,值3…);

# 插入多条记录
    语法:
    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
                    WHERE …;

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=’’;

练习:
    更新MySQL root用户密码为mysql123
    删除除从本地登录的root用户以外的所有用户
    

单表查询

SELECT 字段1,字段2... FROM 表名
      WHERE 条件
      GROUP BY field
      HAVING 筛选
      ORDER BY field
      LIMIT 限制条数

执行优先级(重点)

由上到下, 按顺序执行, 没有就跳过:

  1. where: 约束条件;
  2. group by: 分组;
  3. having: 过滤;
  4. select: ...;
  5. distinct: 去重;
  6. order by: 排序;
  7. limit: 显示条数;

步骤:

  1. 找到表: from table_name;
  2. 拿着where指定的约束条件,去文件/表中取出一条条记录;
  3. 将取出的一条条记录进行分组group by,如果没有group by,则整体作为一组;
  4. 将分组的结果进行having过滤;
  5. 执行select;
  6. distinct去重;
  7. 将结果按条件排序:order by
  8. 限制结果的显示条数: limit

准备表和记录

# 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,
    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 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),
('成龙','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)
;

简单查询

# 查询所有数据
    SELECT * FROM employee;            

# 查询特定字段类的数据
    SELECT name,salary FROM employee;   

# 避免重复DISTINCT
    SELECT DISTINCT post FROM employee;    

# 通过四则运算查询
    SELECT name, salary*12 FROM employee;
    SELECT name, salary*12 AS Annual_salary FROM employee;  # 重新命名
    SELECT name, salary*12 Annual_salary FROM employee;     # 重新命名  

# 定义显示格式
   CONCAT() 函数用于连接字符串
   SELECT CONCAT('姓名: ',name,'  年薪: ', salary*12)  AS Annual_salary 
   FROM employee;
   
   CONCAT_WS() 第一个参数为分隔符
   SELECT CONCAT_WS(':',name,salary*12)  AS Annual_salary 
   FROM employee;

#  练习
1. 查出所有员工的名字,薪资,格式为: <名字:egon>    <薪资:3000>
    select concat('<名字', name,'>', '    <薪资', salary, '>') from employee;
    
2. 查出所有的岗位(去掉重复)
    select distinct post from employee;

3. 查出所有员工名字,以及他们的年薪,年薪的字段名为annual_year
    select name, salary*12 as annual_salary from employee;

WHERE

  1. 比较运算符:>, <, >=, <=, <>, !=;
  2. between 80 and 100 值在80100之间;
  3. in(80,90,100)值是102030;
  4. like ‘egon%‘:pattern可以是%_, %表示任意多字符, _表示一个字符;
  5. 逻辑运算符:在多个条件直接可以使用逻辑运算符 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
    ps:
        执行
        update employee set post_comment='' where id=2;
        再用上条查看,就会有结果了
        
        
# 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__';


# 练习
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

  1. 分组发生在关键字where约束之后,即分组是基于where之后得到的记录而进行的;
  2. 分组指的是将所有记录按照 某个相同字段 进行归类,比如针对员工信息表的职位,或者按照性别进行分组等;
  3. 为何要分组呢?

    1. 取每个部门的最高工资
    2. 取每个部门的员工数
    3. 取男人数和女人数
    4. 小窍门:这个字后面的字段,就是我们分组的依据
  4. 可以按照任意字段分组,但是分组完毕后,比如group by post,只能查看post字段,如果想查看组内信息,需要借助于聚合函数;

# 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

Having条件在group by之后执行,Having中可以使用分组的字段,无法直接取到其他字段,可以使用聚合函数.

# 练习
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

# 按单列排序, 默认升序
    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;

正则表达式查询

SELECT * FROM employee WHERE name REGEXP '^ale';

SELECT * FROM employee WHERE name REGEXP 'on$';

SELECT * FROM employee WHERE name REGEXP 'm{2}';


小结:对字符串匹配的方式
WHERE name = 'egon';        # 准确查询
WHERE name LIKE 'yua%';     # 模糊查询
WHERE name REGEXP 'on$';  # 模糊查询


# 练习
查看所有员工中名字是jin开头,n或者g结果的员工信息
    select * from emp where name regexp "^jin.*[ng]$";

以上是关于数据库03: 表记录操作与查询的主要内容,如果未能解决你的问题,请参考以下文章

面向对象数据库设计与应用 04 - 数据表操作与查询

使用触发器对学生表操作进行日志记录

BaseDAO使用

MySQL表的操作

【Mysql】查询优化——减少回表操作

标准 sql 查询以获取与另一个表匹配的记录字段(Google BigQuery)