相关学习笔记:
- #子查询
- /*
- 含义:
- 出现在其他语句中的select语句,称为子查询或内查询
- 外部的查询语句,称为主查询或外查询
- 分类:
- 按子查询出现的位置:
- select后面:
- 仅仅支持标量子查询
-
- from后面:
- 支持表子查询
- where或having后面:★
- 标量子查询(单行) √
- 列子查询 (多行) √
-
- 行子查询
-
- exists后面(相关子查询)
- 表子查询
- 按结果集的行列数不同:
- 标量子查询(结果集只有一行一列)
- 列子查询(结果集只有一列多行)
- 行子查询(结果集有一行多列)
- 表子查询(结果集一般为多行多列)
- */
-
-
- #一、where或having后面
- /*
- 1、标量子查询(单行子查询)
- 2、列子查询(多行子查询)
- 3、行子查询(多列多行)
- 特点:
- ①子查询放在小括号内
- ②子查询一般放在条件的右侧
- ③标量子查询,一般搭配着单行操作符使用
- > < >= <= = <>
- 列子查询,一般搭配着多行操作符使用
- in、any/some、all
- ④子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
- */
- #1.标量子查询(重点)
- #案例1:谁的工资比 Abel 高?
- SELECT `last_name`
- FROM `employees`
- WHERE salary>(SELECT salary FROM `employees` WHERE `last_name`='Abel');
- #案例2:返回job_id与141号员工相同,salary比143号员工多的员工 姓名,job_id 和工资
- SELECT `last_name`,`job_id`,`salary`
- FROM `employees`
- WHERE `job_id` = (SELECT `job_id` FROM `employees` WHERE `employee_id`=141)
- AND salary > (SELECT salary FROM `employees` WHERE `employee_id`=143);
- #案例3:返回公司工资最少的员工的last_name,job_id和salary
- SELECT `last_name`,`job_id`,`salary`
- FROM `employees`
- WHERE salary=(SELECT MIN(salary) FROM `employees`);
- #案例4:查询最低工资大于50号部门最低工资的部门id和其最低工资
- SELECT `department_id`,MIN(salary)
- FROM `employees`
- GROUP BY `department_id`
- HAVING MIN(salary)>(SELECT MIN(salary) FROM `employees` WHERE `department_id`=50);
-
- #2.列子查询(多行子查询)
- #案例1:返回location_id是1400或1700的部门中的所有员工姓名
- SELECT `last_name`
- FROM `employees`
- WHERE `department_id` IN
- (SELECT `department_id`
- FROM `departments`
- WHERE `location_id` IN (1400,1700));
- #案例2:返回其它工种中比job_id为‘IT_PROG’工种任一工资低的员工的员工号、姓名、job_id 以及salary
- SELECT `employee_id`,`last_name`,`job_id`,`salary`
- FROM `employees`
- WHERE salary < ANY
- (SELECT salary
- FROM `employees`
- WHERE `job_id` = 'IT_PROG')
- AND `job_id` != 'IT_PROG';
- #案例3:返回其它部门中比job_id为‘IT_PROG’部门所有工资都低的员工的员工号、姓名、job_id 以及salary
- SELECT last_name,employee_id,job_id,salary
- FROM employees
- WHERE salary<ALL(
- SELECT DISTINCT salary
- FROM employees
- WHERE job_id = 'IT_PROG'
-
- ) AND job_id<>'IT_PROG';
-
- #3、行子查询(结果集一行多列或多行多列)
- #案例:查询员工编号最小并且工资最高的员工信息
- SELECT *
- FROM `employees`
- WHERE (`employee_id`,`salary`) =
- (SELECT MIN(`employee_id`),MAX(salary) FROM `employees`);
-
- #二、select后面
- /*
- 仅仅支持标量子查询
- */
-
- #案例:查询每个部门的员工个数
- SELECT d.`department_name`,(
- SELECT COUNT(*) FROM `employees` e WHERE e.`department_id` = d.`department_id`
- ) 员工人数
- FROM `departments` d;
- #案例2:查询员工号=102的部门名
- SELECT `department_name`
- FROM `departments` d
- INNER JOIN `employees` e
- ON d.`department_id` = e.`department_id`
- WHERE `employee_id` = 102;
-
- #三、from后面
- /*
- 将子查询结果充当一张表,要求必须起别名
- */
-
- #案例:查询每个部门的平均工资的工资等级
- SELECT Ag_dep.*,j.`grade_level`
- FROM(
- SELECT `department_id`,AVG(salary) ag
- FROM `employees`
- GROUP BY `department_id`
- ) Ag_dep
- INNER JOIN `job_grades` j
- ON Ag_dep.ag BETWEEN `lowest_sal` AND `highest_sal`;
-
- #四、exists后面(相关子查询)
-
- /*
- 语法:
- exists(完整的查询语句)
- 结果:
- 1或0
- */
-
- SELECT EXISTS(SELECT employee_id FROM employees WHERE salary=300000);
-
- #案例1:查询有员工的部门名
- #用exists实现
- SELECT `department_name`
- FROM `departments` d
- WHERE EXISTS(
- SELECT *
- FROM `employees` e
- WHERE d.`department_id`=e.`department_id`
- );
- #用in来实现
- SELECT `department_name`
- FROM `departments` d
- WHERE d.`department_id` IN (
- SELECT `department_id`
- FROM `employees`);
- #案例2:查询没有女朋友的男神信息
- #in实现
- SELECT bo.*
- FROM `boys` bo
- WHERE bo.`id` NOT IN (
- SELECT `boyfriend_id`
- FROM `beauty`);
- #exists实现
- SELECT bo.*
- FROM `boys` bo
- WHERE NOT EXISTS(
- SELECT `boyfriend_id`
- FROM `beauty` b
- WHERE bo.`id`=b.`boyfriend_id`);
- #课后习题
- #1.查询和Zlotkey相同部门的员工姓名和工资
- SELECT `last_name`,salary
- FROM `employees`
- WHERE `department_id` = (
- SELECT `department_id`
- FROM `employees`
- WHERE `last_name`='Zlotkey');
- #2.查询工资比公司平均工资高的员工的员工号,姓名和工资。
- SELECT `employee_id`,`last_name`,salary
- FROM `employees`
- WHERE salary>(
- SELECT AVG(salary)
- FROM `employees`);
- #3.查询各部门中工资比本部门平均工资高的员工的员工号, 姓名和工资
- SELECT `employee_id`,`last_name`,`salary`
- FROM `employees` e
- INNER JOIN (
- SELECT `department_id`,AVG(salary) ag
- FROM `employees`
- GROUP BY `department_id`
- ) b
- ON e.`department_id`=b.`department_id`
- WHERE salary > b.ag;
- #4.查询和姓名中包含字母u的员工在相同部门的员工的员工号和姓名
- SELECT `employee_id`,`last_name`
- FROM `employees`
- WHERE `department_id` IN(
- SELECT `department_id`
- FROM `employees`
- WHERE `last_name` LIKE '%u%'
- );
- #5. 查询在部门的location_id为1700的部门工作的员工的员工号
- SELECT `employee_id`
- FROM `employees`
- WHERE `department_id` IN(
- SELECT `department_id`
- FROM `departments`
- WHERE `location_id`=1700
- );
- #6.查询管理者是King的员工姓名和工资
- SELECT `last_name`,`salary`
- FROM `employees`
- WHERE `manager_id` IN (
- SELECT `employee_id`
- FROM `employees`
- WHERE `last_name`='K_ing'
- );
- #7.查询工资最高的员工的姓名,要求first_name和last_name显示为一列,列名为 姓.名
- SELECT CONCAT(`last_name`,`first_name`) '姓.名'
- FROM `employees`
- WHERE salary=(
- SELECT MAX(salary)
- FROM `employees`
- );
更新一下子查询经典案例习题,这些题拿下了子查询基本就掌握了。
- #子查询经典案例
- # 1. 查询工资最低的员工信息: last_name, salary
- SELECT `last_name`,salary
- FROM `employees`
- WHERE salary = (
- SELECT MIN(salary)
- FROM `employees`
- );
-
- # 2. 查询平均工资最低的部门信息
- # 本人解法(用到两个select):
- # 先查各部门的平均工资,再按平均工资升序排序,再用limit取第一行结果,此时得到的是个一行两列的表。再将此表和`departments`表内连接,连接条件为`department_id`字段相同,即可。
- SELECT d.`department_id`,d.`department_name`,d.`manager_id`,d.`location_id`
- FROM `departments` d
- INNER JOIN
- (SELECT AVG(salary) ag,d.`department_id`
- FROM `departments` d
- INNER JOIN `employees` e
- ON d.`department_id`=e.`department_id`
- GROUP BY `department_id`
- ORDER BY ag ASC
- LIMIT 1) b
- ON d.`department_id`=b.`department_id`;
- # 上述办法可以优化一下,自己构造的那个表可以只查询`department_id`字段
- SELECT *
- FROM `departments`
- WHERE `department_id`=(
- SELECT `department_id`
- FROM `employees`
- GROUP BY `department_id`
- ORDER BY AVG(salary)
- LIMIT 1
- );
- #(尚硅谷老师用的方式一这里就不列出来了)
-
- # 3. 查询平均工资最低的部门信息和该部门的平均工资
- # ps:和上一题差不多,把该部门的平均工资select出来即可
- SELECT d.`department_id`,d.`department_name`,d.`manager_id`,d.`location_id`,b.ag
- FROM `departments` d
- INNER JOIN
- (SELECT AVG(salary) ag,d.`department_id`
- FROM `departments` d
- INNER JOIN `employees` e
- ON d.`department_id`=e.`department_id`
- GROUP BY `department_id`
- ORDER BY ag ASC
- LIMIT 1) b
- ON d.`department_id`=b.`department_id`;
-
- # 4. 查询平均工资最高的 job 信息
- SELECT * FROM `jobs`
- WHERE `job_id` = (
- SELECT `job_id` FROM `employees`
- GROUP BY `job_id`
- ORDER BY AVG(`salary`) DESC
- LIMIT 1
- );
-
- # 5. 查询平均工资高于公司平均工资的部门有哪些?
- SELECT `department_id` FROM `employees`
- GROUP BY `department_id`
- HAVING AVG(salary) > (
- SELECT AVG(salary) FROM `employees`
- );
-
-
- # 6. 查询出公司中所有 manager 的详细信息.
- SELECT * FROM `employees`
- WHERE `employee_id` IN (
- SELECT `manager_id` FROM `employees`
- );
-
- # 7. 各个部门中 最高工资中最低的那个部门的 最低工资是多少
- SELECT MIN(salary) ,department_id
- FROM employees
- WHERE department_id=(
- SELECT department_id
- FROM employees
- GROUP BY department_id
- ORDER BY MAX(salary)
- LIMIT 1
- );
-
- # 8. 查询平均工资最高的部门的 manager 的详细信息: last_name, department_id, email, salary
- SELECT `last_name`,e.`department_id`,`email`,`salary`
- FROM `employees` e
- INNER JOIN `departments` d
- ON d.`manager_id`=e.`employee_id`
- WHERE d.`department_id` = (
- SELECT `department_id`
- FROM `employees`
- GROUP BY `department_id`
- ORDER BY AVG(salary) DESC
- LIMIT 1
- );