MySQL子查询

子查询(嵌套查询)

子查询是指一个查询语句嵌套在另一个查询语句的内部的查询

eg:要查询员工工资比‘Abel’高的员工名字
SELECT name,salary     #外查询(主查询)
FROM employees
WHERE salary > (#查询'Abel'的工资
                SELECT salary       #内查询(子查询)
                FROM employees
                WHERE name = 'Abel'
                );
  • 子查询在主查询之前执行
  • 子查询的结果供外查询使用
  • 子查询在()内
  • 单行操作符对应单行子查询,多行操作符对应多行子查询

子查询的分类

角度一 (内查询返回结果的条目):

角度二 (内查询是否执行多次):

  • 相关子查询:内查询的结果与外查询的条件有关

  • 不相管子查询:内查询的结果与外查询的条件无关

eg:查询工资大于本部门的员工:相关

​ 查询工资大于公司平均工资的员工:不相关

单行子查询

单行比较操作符

=、<、<=、>、>=、<>

HARING中的子查询

  • 先执行子查询
  • 向HARING中返回结果
eg:要查询最低工资大于50号部门最低工资的部门id
SELECT department_id 
FROM employees
GROUP BY department_id
HARING min(salary) > (
                     SELECT min(salary)       
                     FROM employees
                     WHERE deppartment_id = 50
                    );

CASE中的子查询

eg:查询员工的id,其部门id与地址id是1800的员工相同的是'China',不同的是'usa'
SELECT employees_id,(CASE department_id WHEN (SELECT department_id
                                              FROM departments
                                              WHERE location_id = 1800) RHEN 'china'  
                                        else 'usa' END ) "location"(别名)

FROM employees;


子查询的空值问题

内查询结果是空或是没有,不会报错,但是不会显示结果

非法使用子查询

单行的操作符对应多行的子查询等情况

多行子查询

  • 也叫做集合比较子查询
  • 内查询返回多行
  • 使用多行操作符

多行比较操作符

  • IN:
SELECT name,salary     
FROM employees
WHERE salary IN (#各部门的最低工资
                SELECT MIN(salary)       
                FROM employees
                GROUP BY department_id
                );
  • ANY \ ALL
eg:返回其他job_id中比job_id为'IT'部门的 *任一* 工资低的员工的员工id
SELECT id
FROM employees
WHERE job_id <> 'IT'
and salary < ANY (SELECT salary
                  FROM employees
                  WHERE job_id ='IT'
                 );

eg:返回其他job_id中比job_id为'IT'部门的 *所有* 工资低的员工的员工id
SELECT id
FROM employees
WHERE job_id <> 'IT'
and salary < ALL (SELECT salary
                  FROM employees
                  WHERE job_id ='IT'
                 );
查平均工资最低的部门id
方式一:在FROM中使用子查询
SELECT department_id
FROM employees
GROUP BY department_id
HARING AVG(salary) = (SELECT MIN(avg_sal)
                      FROM(SELECT AVG(salary) avg_sal #把查出的各部门的平均工资当成一个新表来使用 
                           FROM employees
                           GROUP BY department_id
                          ) "t_dept_avg_sal"
);

方式二:使用ALL
SELECT department_id
FROM employees
GROUP BY department_id
HARING AVG(salary) <= ALL (SELECT AVG(salary) 
    /*在内查询的结果中*/    FROM employees
                           GROUP BY department_id
                          );

空值问题

内查询结果有null时,外查询不会出结果

相关子查询

相关子查询的执行过程

子查询的执行条件依赖于外部查询,每执行一次外查询,内查询都要重新计算一遍

eg:查员工工资>本部门的平均工资的id
# 每遍历一行数据都要进行匹配
SELECT id
FROM employees t1
WHERE salary > (SELECT AVG(salary)#此时内查询的结果就是传入数据的员工的部门的平均工资
                FROM employees t2
                WHERE t2.department_id = t1.department_id              
               );          

在 SELECT 中,除了GROUP BY 和LIMIT 中不能写子查询外,其他位置都可以使用

EXISTS和 NOT EXISTS关键字

用来检查在子查询中是否存在满足条件的行

类似于C语言中的break

EXISTS

  • 不存在满足条件的行

​ 条件返回FALSS

​ 继续在子查询中寻找

  • 存在满足条件的行

​ 不在子查询中继续寻找

​ 条件返回TRUE

查询公司管理者的ID
方式1:自连接
SELECT DISTINCT t2.employee_id   #去重
FROM employees t1 JOIN employees t2
ON t1.manger_id = t2.employee_id;

方式2:子查询
SELECT employee_id
FROM employees 
WHERE employee_id IN (SELECT DISTINCT manger_id
                       FROM employees                                          );

方式3:使用EXISTS
SELECT t1.employee_id
FROM employees t1
WHERE EXISTS  (SELECT *
               FROM employees t2
               WHERE t1.employee_id = t2.manger_id
              );

NOT EXISTS

  • NOT EXISTS表示如果不存在某种条件,则返回TRUE,否则返回FALSS
查询部门表中不存在于员工表的部门ID
方式一:外连接
SELECT t2.department_id
FROM employees t1 RIGHT JOIN departments t2
ON t1.department_name = t2.department_name
WHERE t1.department is null;

方式二:
SELECT department_id
FROM departments t1
WHERE NOT EXISTS(SELECT *
                 FROM employees t2
                 WHERE t1.department_name = t2.department_name
               );

相关更新

相关删除

posted @ 2022-03-06 18:39  T,a,o  阅读(174)  评论(0编辑  收藏  举报