一、环境准备

  1. #创建部门
  2. CREATE TABLE IF NOT EXISTS dept (
  3. did int not null auto_increment PRIMARY KEY,
  4. dname VARCHAR(50) not null COMMENT '部门名称'
  5. )ENGINE=INNODB DEFAULT charset utf8;
  6. #添加部门数据
  7. INSERT INTO `dept` VALUES ('1', '教学部');
  8. INSERT INTO `dept` VALUES ('2', '销售部');
  9. INSERT INTO `dept` VALUES ('3', '市场部');
  10. INSERT INTO `dept` VALUES ('4', '人事部');
  11. INSERT INTO `dept` VALUES ('5', '鼓励部');
  12. -- 创建人员
  13. DROP TABLE IF EXISTS `person`;
  14. CREATE TABLE `person` (
  15. `id` int(11) NOT NULL AUTO_INCREMENT,
  16. `name` varchar(50) NOT NULL,
  17. `age` tinyint(4) DEFAULT '0',
  18. `sex` enum('男','女','人妖') NOT NULL DEFAULT '人妖',
  19. `salary` decimal(10,2) NOT NULL DEFAULT '250.00',
  20. `hire_date` date NOT NULL,
  21. `dept_id` int(11) DEFAULT NULL,
  22. PRIMARY KEY (`id`)
  23. ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
  24. -- 添加人员数据
  25. -- 教学部
  26. INSERT INTO `person` VALUES ('1', 'alex', '28', '人妖', '53000.00', '2010-06-21', '1');
  27. INSERT INTO `person` VALUES ('2', 'wupeiqi', '23', '男', '8000.00', '2011-02-21', '1');
  28. INSERT INTO `person` VALUES ('3', 'egon', '30', '男', '6500.00', '2015-06-21', '1');
  29. INSERT INTO `person` VALUES ('4', 'jingnvshen', '18', '女', '6680.00', '2014-06-21', '1');
  30. -- 销售部
  31. INSERT INTO `person` VALUES ('5', '歪歪', '20', '女', '3000.00', '2015-02-21', '2');
  32. INSERT INTO `person` VALUES ('6', '星星', '20', '女', '2000.00', '2018-01-30', '2');
  33. INSERT INTO `person` VALUES ('7', '格格', '20', '女', '2000.00', '2018-02-27', '2');
  34. INSERT INTO `person` VALUES ('8', '周周', '20', '女', '2000.00', '2015-06-21', '2');
  35. -- 市场部
  36. INSERT INTO `person` VALUES ('9', '月月', '21', '女', '4000.00', '2014-07-21', '3');
  37. INSERT INTO `person` VALUES ('10', '安琪', '22', '女', '4000.00', '2015-07-15', '3');
  38. -- 人事部
  39. INSERT INTO `person` VALUES ('11', '周明月', '17', '女', '5000.00', '2014-06-21', '4');
  40. -- 鼓励部
  41. INSERT INTO `person` VALUES ('12', '苍老师', '33', '女', '1000000.00', '2018-02-21', null);
  42. 创建表和数据

二、概述

1、多表查询语法

  1. select 字段1,字段2... from 1,表2... [where 条件]

2、笛卡尔乘积

如果不加条件直接进行查询,则会出现以下效果,这种结果我们称之为 笛卡尔乘积
笛卡尔乘积公式 : A表中数据条数 * B表中数据条数 = 笛卡尔乘积
举例:

  1. #查询人员和部门所有信息
  2. select * from person,dept;

结果:

  1. mysql> select * from person,dept;
  2. +----+------------+-----+------+---------+------------+---------+-----+--------+
  3. | id | name | age | sex | salary | hire_date | dept_id | did | dname |
  4. +----+------------+-----+------+---------+------------+---------+-----+--------+
  5. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 1 | 教学部 |
  6. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 2 | 销售部 |
  7. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 3 | 市场部 |
  8. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 4 | 人事部 |
  9. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 5 | 鼓励部 |
  10. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 1 | 教学部 |
  11. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 2 | 销售部 |
  12. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 3 | 市场部 |
  13. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 4 | 人事部 |
  14. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 5 | 鼓励部 |
  15. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 1 | 教学部 |
  16. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 2 | 销售部 |
  17. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 3 | 市场部 |
  18. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 4 | 人事部 |
  19. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 5 | 鼓励部 |
  20. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 | 1 | 教学部 |
  21. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 | 2 | 销售部 |
  22. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 | 3 | 市场部 |
  23. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 | 4 | 人事部 |
  24. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 | 5 | 鼓励部 |
  25. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 1 | 教学部 |
  26. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 2 | 销售部 |
  27. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 3 | 市场部 |
  28. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 4 | 人事部 |
  29. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 5 | 鼓励部 |
  30. | 6 | 星星 | 20 | | 2000 | 2018-01-30 | 2 | 1 | 教学部 |
  31. | 6 | 星星 | 20 | | 2000 | 2018-01-30 | 2 | 2 | 销售部 |
  32. | 6 | 星星 | 20 | | 2000 | 2018-01-30 | 2 | 3 | 市场部 |
  33. | 6 | 星星 | 20 | | 2000 | 2018-01-30 | 2 | 4 | 人事部 |
  34. | 6 | 星星 | 20 | | 2000 | 2018-01-30 | 2 | 5 | 鼓励部 |
  35. | 7 | 格格 | 20 | | 2000 | 2018-02-27 | 2 | 1 | 教学部 |
  36. | 7 | 格格 | 20 | | 2000 | 2018-02-27 | 2 | 2 | 销售部 |
  37. | 7 | 格格 | 20 | | 2000 | 2018-02-27 | 2 | 3 | 市场部 |
  38. | 7 | 格格 | 20 | | 2000 | 2018-02-27 | 2 | 4 | 人事部 |
  39. | 7 | 格格 | 20 | | 2000 | 2018-02-27 | 2 | 5 | 鼓励部 |
  40. | 8 | 周周 | 20 | | 2000 | 2015-06-21 | 2 | 1 | 教学部 |
  41. | 8 | 周周 | 20 | | 2000 | 2015-06-21 | 2 | 2 | 销售部 |
  42. | 8 | 周周 | 20 | | 2000 | 2015-06-21 | 2 | 3 | 市场部 |
  43. | 8 | 周周 | 20 | | 2000 | 2015-06-21 | 2 | 4 | 人事部 |
  44. | 8 | 周周 | 20 | | 2000 | 2015-06-21 | 2 | 5 | 鼓励部 |
  45. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 1 | 教学部 |
  46. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 2 | 销售部 |
  47. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 3 | 市场部 |
  48. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 4 | 人事部 |
  49. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 5 | 鼓励部 |
  50. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 1 | 教学部 |
  51. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 2 | 销售部 |
  52. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 3 | 市场部 |
  53. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 4 | 人事部 |
  54. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 5 | 鼓励部 |
  55. | 11 | 周明月 | 17 | | 5000 | 2014-06-21 | 4 | 1 | 教学部 |
  56. | 11 | 周明月 | 17 | | 5000 | 2014-06-21 | 4 | 2 | 销售部 |
  57. | 11 | 周明月 | 17 | | 5000 | 2014-06-21 | 4 | 3 | 市场部 |
  58. | 11 | 周明月 | 17 | | 5000 | 2014-06-21 | 4 | 4 | 人事部 |
  59. | 11 | 周明月 | 17 | | 5000 | 2014-06-21 | 4 | 5 | 鼓励部 |
  60. | 12 | 苍老师 | 33 | | 1000000 | 2018-02-21 | NULL | 1 | 教学部 |
  61. | 12 | 苍老师 | 33 | | 1000000 | 2018-02-21 | NULL | 2 | 销售部 |
  62. | 12 | 苍老师 | 33 | | 1000000 | 2018-02-21 | NULL | 3 | 市场部 |
  63. | 12 | 苍老师 | 33 | | 1000000 | 2018-02-21 | NULL | 4 | 人事部 |
  64. | 12 | 苍老师 | 33 | | 1000000 | 2018-02-21 | NULL | 5 | 鼓励部 |
  65. +----+------------+-----+------+---------+------------+---------+-----+--------+
  66. 60 rows in set

三、多表查询类型

1、多表联合查询

  1. #查询人员和部门所有信息
  2. select * from person p,dept d where p.dept_id = d.did;

结果:

  1. mysql> select * from person p,dept d where p.dept_id = d.did;
  2. +----+------------+-----+------+--------+------------+---------+-----+--------+
  3. | id | name | age | sex | salary | hire_date | dept_id | did | dname |
  4. +----+------------+-----+------+--------+------------+---------+-----+--------+
  5. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 1 | 教学部 |
  6. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 1 | 教学部 |
  7. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 1 | 教学部 |
  8. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 | 1 | 教学部 |
  9. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 2 | 销售部 |
  10. | 6 | 星星 | 20 | | 2000 | 2018-01-30 | 2 | 2 | 销售部 |
  11. | 7 | 格格 | 20 | | 2000 | 2018-02-27 | 2 | 2 | 销售部 |
  12. | 8 | 周周 | 20 | | 2000 | 2015-06-21 | 2 | 2 | 销售部 |
  13. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 3 | 市场部 |
  14. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 3 | 市场部 |
  15. | 11 | 周明月 | 17 | | 5000 | 2014-06-21 | 4 | 4 | 人事部 |
  16. +----+------------+-----+------+--------+------------+---------+-----+--------+
  17. 11 rows in set

备注:多表查询时,一定要找到两个表中相互关联的字段,并且作为条件使用
图解:
image.png

2、多表连接查询

  1. #多表连接查询语法(重点)
  2. SELECT 字段列表
  3. FROM 1 INNER|LEFT|RIGHT JOIN 2
  4. ON 1.字段 = 2.字段;内连接查询 (只显示符合条件的数据)

(1)内连接查询 (只显示符合条件的数据)

  1. #查询人员和部门所有信息
  2. select * from person inner join dept on person.dept_id =dept.did;

结果:

  1. mysql> #查询人员和部门所有信息
  2. select * from person inner join dept on person.dept_id =dept.did;
  3. +----+------------+-----+------+--------+------------+---------+-----+--------+
  4. | id | name | age | sex | salary | hire_date | dept_id | did | dname |
  5. +----+------------+-----+------+--------+------------+---------+-----+--------+
  6. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 1 | 教学部 |
  7. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 1 | 教学部 |
  8. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 1 | 教学部 |
  9. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 | 1 | 教学部 |
  10. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 2 | 销售部 |
  11. | 6 | 星星 | 20 | | 2000 | 2018-01-30 | 2 | 2 | 销售部 |
  12. | 7 | 格格 | 20 | | 2000 | 2018-02-27 | 2 | 2 | 销售部 |
  13. | 8 | 周周 | 20 | | 2000 | 2015-06-21 | 2 | 2 | 销售部 |
  14. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 3 | 市场部 |
  15. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 3 | 市场部 |
  16. | 11 | 周明月 | 17 | | 5000 | 2014-06-21 | 4 | 4 | 人事部 |
  17. +----+------------+-----+------+--------+------------+---------+-----+--------+
  18. 11 rows in set

备注: 内连接查询与多表联合查询的效果是一样的.
图解:
image.png

(2)左外连接查询 (左边表中的数据优先全部显示)

  1. #查询人员和部门所有信息
  2. select * from person p left join dept d on p.dept_id =d.did;

结果:

  1. mysql> select * from person p left join dept d on p.dept_id =d.did;
  2. +----+------------+-----+------+---------+------------+---------+------+--------+
  3. | id | name | age | sex | salary | hire_date | dept_id | did | dname |
  4. +----+------------+-----+------+---------+------------+---------+------+--------+
  5. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 1 | 教学部 |
  6. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 1 | 教学部 |
  7. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 1 | 教学部 |
  8. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 | 1 | 教学部 |
  9. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 2 | 销售部 |
  10. | 6 | 星星 | 20 | | 2000 | 2018-01-30 | 2 | 2 | 销售部 |
  11. | 7 | 格格 | 20 | | 2000 | 2018-02-27 | 2 | 2 | 销售部 |
  12. | 8 | 周周 | 20 | | 2000 | 2015-06-21 | 2 | 2 | 销售部 |
  13. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 3 | 市场部 |
  14. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 3 | 市场部 |
  15. | 11 | 周明月 | 17 | | 5000 | 2014-06-21 | 4 | 4 | 人事部 |
  16. | 12 | 苍老师 | 33 | | 1000000 | 2018-02-21 | NULL | NULL | NULL |
  17. +----+------------+-----+------+---------+------------+---------+------+--------+
  18. 12 rows in set

图解:
image.png

(3)右外连接查询 (右边表中的数据优先全部显示)

  1. #查询人员和部门所有信息
  2. select * from person p right join dept d on p.dept_id =d.did;

结果:

  1. mysql> select * from person p right join dept d on p.dept_id =d.did;
  2. +------+------------+------+------+--------+------------+---------+-----+--------+
  3. | id | name | age | sex | salary | hire_date | dept_id | did | dname |
  4. +------+------------+------+------+--------+------------+---------+-----+--------+
  5. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 1 | 教学部 |
  6. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 1 | 教学部 |
  7. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 1 | 教学部 |
  8. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 | 1 | 教学部 |
  9. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 2 | 销售部 |
  10. | 6 | 星星 | 20 | | 2000 | 2018-01-30 | 2 | 2 | 销售部 |
  11. | 7 | 格格 | 20 | | 2000 | 2018-02-27 | 2 | 2 | 销售部 |
  12. | 8 | 周周 | 20 | | 2000 | 2015-06-21 | 2 | 2 | 销售部 |
  13. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 3 | 市场部 |
  14. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 3 | 市场部 |
  15. | 11 | 周明月 | 17 | | 5000 | 2014-06-21 | 4 | 4 | 人事部 |
  16. | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 5 | 鼓励部 |
  17. +------+------------+------+------+--------+------------+---------+-----+--------+
  18. 12 rows in set

备注:正好与左外连接相反

(4)全连接查询(显示左右表中全部数据)

定义:是在内连接的基础上增加 左右两边没有显示的数据
注意:
1、mysql并不支持全连接 full JOIN 关键字
2、mysql 提供了 UNION 关键字.使用 UNION 可以间接实现 full JOIN 功能

  1. #查询人员和部门的所有数据
  2. SELECT * FROM person LEFT JOIN dept ON person.dept_id = dept.did
  3. UNION
  4. SELECT * FROM person RIGHT JOIN dept ON person.dept_id = dept.did;

结果:

  1. mysql> SELECT * FROM person LEFT JOIN dept ON person.dept_id = dept.did
  2. UNION
  3. SELECT * FROM person RIGHT JOIN dept ON person.dept_id = dept.did;
  4. +------+------------+------+------+---------+------------+---------+------+--------+
  5. | id | name | age | sex | salary | hire_date | dept_id | did | dname |
  6. +------+------------+------+------+---------+------------+---------+------+--------+
  7. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 1 | 教学部 |
  8. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 1 | 教学部 |
  9. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 1 | 教学部 |
  10. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 | 1 | 教学部 |
  11. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 2 | 销售部 |
  12. | 6 | 星星 | 20 | | 2000 | 2018-01-30 | 2 | 2 | 销售部 |
  13. | 7 | 格格 | 20 | | 2000 | 2018-02-27 | 2 | 2 | 销售部 |
  14. | 8 | 周周 | 20 | | 2000 | 2015-06-21 | 2 | 2 | 销售部 |
  15. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 3 | 市场部 |
  16. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 3 | 市场部 |
  17. | 11 | 周明月 | 17 | | 5000 | 2014-06-21 | 4 | 4 | 人事部 |
  18. | 12 | 苍老师 | 33 | | 1000000 | 2018-02-21 | NULL | NULL | NULL |
  19. | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 5 | 鼓励部 |
  20. +------+------------+------+------+---------+------------+---------+------+--------+
  21. 13 rows in set

3、复杂条件多表查询

查询出 教学部 年龄大于20岁,并且工资小于40000的员工,按工资倒序排列.(要求:分别使用多表联合查询和内连接查询)

  1. #多表联合查询方式
  2. select * from person p,dept d where p.dept_id= d.did
  3. and age>20
  4. and salary <40000
  5. ORDER BY salary DESC;
  6. #内连接方式
  7. SELECT * FROM person p INNER JOIN dept d ON p.dept_id= d.did
  8. and age>20
  9. and salary <40000
  10. ORDER BY salary DESC;

结果:

  1. +----+---------+-----+-----+--------+------------+---------+-----+--------+
  2. | id | name | age | sex | salary | hire_date | dept_id | did | dname |
  3. +----+---------+-----+-----+--------+------------+---------+-----+--------+
  4. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 1 | 教学部 |
  5. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 1 | 教学部 |
  6. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 3 | 市场部 |
  7. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 3 | 市场部 |
  8. +----+---------+-----+-----+--------+------------+---------+-----+--------+
  9. 4 rows in set

查询每个部门中最高工资和最低工资是多少,显示部门名称

  1. #联合查询方式
  2. SELECT MAX(p.salary),MIN(p.salary),d.dname from person p , dept d where p.dept_id = d.did GROUP BY p.dept_id;
  3. #内连接方式
  4. SELECT MAX(p.salary),MIN(p.salary),d.dname from person p INNER JOIN dept d on p.dept_id = d.did GROUP BY p.dept_id;

结果:

  1. +---------------+---------------+--------+
  2. | MAX(p.salary) | MIN(p.salary) | dname |
  3. +---------------+---------------+--------+
  4. | 53000 | 6500 | 教学部 |
  5. | 3000 | 2000 | 销售部 |
  6. | 4000 | 4000 | 市场部 |
  7. | 5000 | 5000 | 人事部 |
  8. +---------------+---------------+--------+
  9. 4 rows in set

4、子查询

子查询(嵌套查询): 查多次, 多个select
注意: 第一次的查询结果可以作为第二次的查询的 条件 或者 表名 使用.
子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字. 还可以包含比较运算符:= 、 !=、> 、<等.

(1)作为表名使用

  1. select * from (select * from person) as 表名;
  2. ps:需要注意的是: 一条语句中可以有多个这样的子查询,在执行时,最里层括号(sql语句) 具有优先执行权.
  3. 注意: as 后面的表名称不能加引号('')

求最高工资那个人的姓名和薪水

  1. select p.name,p.salary from person p where p.salary=(select max(salary) from person);

结果:

  1. +--------+---------+
  2. | name | salary |
  3. +--------+---------+
  4. | 苍老师 | 1000000 |
  5. +--------+---------+
  6. 1 row in set

思路:先查询出最高工资,再查询出姓名和薪水,最高工资作为子查询的条件。

求工资高于所有人员平均工资的人员

  1. SELECT name,salary from person where salary > (SELECT avg(p.salary) FROM person p);

结果:

  1. +--------+---------+
  2. | name | salary |
  3. +--------+---------+
  4. | 苍老师 | 1000000 |
  5. +--------+---------+
  6. 1 row in set

思路:先查询除平均工资,再查询出姓名和薪水,平均工资作为其子查询的条件

(2)练习

1、查询平均年龄在20以上的部门名称

  1. #查询平均年龄在20以上的部门名称
  2. #多表联合查询方式
  3. SELECT d.did as '部门id',d.dname as "部门名称",AVG(p.age) as "部门平均年龄" from person p,dept d WHERE p.dept_id = d.did GROUP BY d.did HAVING AVG(p.age) > 20;
  4. #子查询方式
  5. SELECT * FROM dept WHERE dept.did IN ( SELECT dept_id FROM person GROUP BY dept_id HAVING avg(person.age) > 20 );

结果:

  1. +--------+----------+--------------+
  2. | 部门id | 部门名称 | 部门平均年龄 |
  3. +--------+----------+--------------+
  4. | 1 | 教学部 | 24.75 |
  5. | 3 | 市场部 | 21.5 |
  6. +--------+----------+--------------+
  7. 2 rows in set

2、查询教学部 下的员工信息

  1. SELECT * FROM person p WHERE p.dept_id in(SELECT d.did from dept d WHERE d.dname = "教学部");

结果:

  1. +----+------------+-----+------+--------+------------+---------+
  2. | id | name | age | sex | salary | hire_date | dept_id |
  3. +----+------------+-----+------+--------+------------+---------+
  4. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 |
  5. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 |
  6. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 |
  7. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 |
  8. +----+------------+-----+------+--------+------------+---------+
  9. 4 rows in set

3、查询大于所有人平均工资的人员的姓名与年龄

  1. SELECT * FROM person where salary >(SELECT AVG(salary) from person);

结果:

  1. +----+--------+-----+-----+---------+------------+---------+
  2. | id | name | age | sex | salary | hire_date | dept_id |
  3. +----+--------+-----+-----+---------+------------+---------+
  4. | 12 | 苍老师 | 33 | | 1000000 | 2018-02-21 | NULL |
  5. +----+--------+-----+-----+---------+------------+---------+
  6. 1 row in set

关键字
any
all
some

5、其他查询方式

(1)临时表查询

查询高于本部门平均工资的人员

  1. #1.先查询部门人员的平均工资
  2. SELECT dept_id,AVG(salary)as sal from person GROUP BY dept_id;
  3. #2.再用人员的工资与部门的平均工资进行比较
  4. SELECT * FROM person as p1,
  5. (SELECT dept_id,AVG(salary)as '平均工资' from person GROUP BY dept_id) as p2
  6. where p1.dept_id = p2.dept_id AND p1.salary >p2.`平均工资`;
  7. ps:在当前语句中,我们可以把上一次的查询结果当前做一张表来使用.因为p2表不是真是存在的,所以:我们称之为 临时表  
  8. 临时表:不局限于自身表,任何的查询结果集都可以认为是一个临时表.

结果:

  1. +----+------+-----+------+--------+------------+---------+---------+--------------+
  2. | id | name | age | sex | salary | hire_date | dept_id | dept_id | 平均工资 |
  3. +----+------+-----+------+--------+------------+---------+---------+--------------+
  4. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 1 | 18545.000000 |
  5. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 2 | 2250.000000 |
  6. +----+------+-----+------+--------+------------+---------+---------+--------------+
  7. 2 rows in set

(2)判断查询 IF关键字

需求1:根据工资高低,将人员划分为两个级别,分别为 高端人群和低端人群。显示效果:姓名,年龄,性别,工资,级别

  1. select p1.*,
  2. IF(p1.salary >10000,'高端人群','低端人群') as '级别'
  3. from person p1;
  4. #ps: 语法: IF(条件表达式,"结果为true",'结果为false');

结果:

  1. +----+------------+-----+------+---------+------------+---------+----------+
  2. | id | name | age | sex | salary | hire_date | dept_id | 级别 |
  3. +----+------------+-----+------+---------+------------+---------+----------+
  4. | 1 | alex | 28 | 人妖 | 53000 | 2010-06-21 | 1 | 高端人群 |
  5. | 2 | wupeiqi | 23 | | 8000 | 2011-02-21 | 1 | 低端人群 |
  6. | 3 | egon | 30 | | 6500 | 2015-06-21 | 1 | 低端人群 |
  7. | 4 | jingnvshen | 18 | | 6680 | 2014-06-21 | 1 | 低端人群 |
  8. | 5 | 歪歪 | 20 | | 3000 | 2015-02-21 | 2 | 低端人群 |
  9. | 6 | 星星 | 20 | | 2000 | 2018-01-30 | 2 | 低端人群 |
  10. | 7 | 格格 | 20 | | 2000 | 2018-02-27 | 2 | 低端人群 |
  11. | 8 | 周周 | 20 | | 2000 | 2015-06-21 | 2 | 低端人群 |
  12. | 9 | 月月 | 21 | | 4000 | 2014-07-21 | 3 | 低端人群 |
  13. | 10 | 安琪 | 22 | | 4000 | 2015-07-15 | 3 | 低端人群 |
  14. | 11 | 周明月 | 17 | | 5000 | 2014-06-21 | 4 | 低端人群 |
  15. | 12 | 苍老师 | 33 | | 1000000 | 2018-02-21 | NULL | 高端人群 |
  16. +----+------------+-----+------+---------+------------+---------+----------+
  17. 12 rows in set

需求2:根据工资高低,统计每个部门人员收入情况,划分为 富人,小资,平民,吊丝 四个级别, 要求统计四个级别分别有多少人

  1. #语法一:
  2. SELECT
  3. CASE WHEN STATE = '1' THEN '成功'
  4. WHEN STATE = '2' THEN '失败'
  5. ELSE '其他' END
  6. FROM 表;
  7. #语法二:
  8. SELECT CASE age
  9. WHEN 23 THEN '23岁'
  10. WHEN 27 THEN '27岁'
  11. WHEN 30 THEN '30岁'
  12. ELSE '其他岁' END
  13. FROM person;
  1. SELECT dname '部门',
  2. sum(case WHEN salary >50000 THEN 1 ELSE 0 end) as '富人',
  3. sum(case WHEN salary between 29000 and 50000 THEN 1 ELSE 0 end) as '小资',
  4. sum(case WHEN salary between 10000 and 29000 THEN 1 ELSE 0 end) as '平民',
  5. sum(case WHEN salary <10000 THEN 1 ELSE 0 end) as '吊丝'
  6. FROM person,dept where person.dept_id = dept.did GROUP BY dept_id;

结果:

  1. +--------+------+------+------+------+
  2. | 部门 | 富人 | 小资 | 平民 | 吊丝 |
  3. +--------+------+------+------+------+
  4. | 教学部 | 1 | 0 | 0 | 3 |
  5. | 销售部 | 0 | 0 | 0 | 4 |
  6. | 市场部 | 0 | 0 | 0 | 2 |
  7. | 人事部 | 0 | 0 | 0 | 1 |
  8. +--------+------+------+------+------+
  9. 4 rows in set

MySQL函数 DATE_SUB()

一、定义

  1. DATE_SUB() 函数从日期减去指定的时间间隔。

二、语法

  1. DATE_SUB(date, INTERVAL expr type)<br /> date 参数是合法的日期表达式。expr 参数是您希望添加的时间间隔。<br /> type 参数可以是下列值:

Type值 说明

MICROSECOND 返回时间或日期时间表达式expr的微秒,这个数字范围为 0 到 999999
SECOND 返回时间秒值,范围为0〜59。
MINUTE 返回时间的分钟,范围为0至59。
HOUR 返回时间的小时部分。返回值的范围为0至23的小时值。然而,TIME值的范围实际上要大得多,所以HOUR可以返回大于23的值。
DAY 返回给定日期的月份的日期部分。
WEEK 返回日期的星期数
MONTH 返回日期的月份,取值范围为0〜12。
QUARTER 返回年份日期的季度值,范围为1〜4
YEAR 返回年份日期,范围为1000〜9999或0

三.某公司面试题:

  1. --表一:
  2. CREATE TABLE `yuhuang_supply_card` (
  3. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id',
  4. `orderId` varchar(50) NOT NULL COMMENT '对内订单号',
  5. `userId` bigint(11) NOT NULL COMMENT '用户id,对应yuhuang_sup_user 表user_id',
  6. `productType` int(11) NOT NULL COMMENT '运营商',
  7. `settlePrice` decimal(7,2) NOT NULL DEFAULT '0.00' COMMENT '订单金额',
  8. `status` int(2) NOT NULL DEFAULT '3' COMMENT '状态,0在售,1已售,2停售,3可售',
  9. `startTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入库时间',
  10. PRIMARY KEY (`id`),
  11. KEY `startTime` (`startTime`),
  12. KEY `idx_status` (`status`)
  13. ) ENGINE=InnoDB AUTO_INCREMENT=66158 DEFAULT CHARSET=utf8 COMMENT='卡密供货订单';
  14. --表二:
  15. CREATE TABLE `yuhuang_sup_user` (
  16. `user_id` bigint(20) NOT NULL AUTO_INCREMENT,
  17. `account` varchar(255) DEFAULT NULL COMMENT '账号',
  18. `status` tinyint(3) NOT NULL DEFAULT '1' COMMENT '0 关闭 1开启',
  19. PRIMARY KEY (`user_id`)
  20. ) ENGINE=InnoDB AUTO_INCREMENT=70372 DEFAULT CHARSET=utf8 COMMENT='用户表';
  1. 要求查询出 <br />三天内每个用户已售的订单总金额、<br />已售的订单总笔数、<br />账号,<br />需要按用户账号排序 <br />其中三天内函数为:date_sub(curdate(),interval 3 day)
  1. SELECT
  2. u.account,
  3. i.sumPrice,
  4. i.countOrder
  5. FROM
  6. (
  7. SELECT
  8. userId,
  9. sum( settlePrice ) sumPrice,
  10. count( userId ) countOrder
  11. FROM
  12. yuhuang_supply_card
  13. WHERE
  14. STATUS = 1
  15. AND date_sub( curdate(), INTERVAL 3 DAY ) < startTime
  16. GROUP BY
  17. userId
  18. ) i,
  19. yuhuang_sup_user u
  20. WHERE
  21. i.userId = u.user_id
  22. ORDER BY
  23. u.account ASC