MySQL 子查询介绍和单行子查询、多行子查询介绍

2020-12-17 0 By admin

子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从MySQL 4.1开始引入。
SQL 中子查询的使用大大增强了 SELECT 查询的能力,因为很多时候查询需要从结果集中获取数据,或者需要从同一个表中先计算得出一个数据结果,然后与这个数据结果(可能是某个标量,也可能是某个集合)进行比较。

一、子查询基本使用

1.1、子查询的基本语法结构

Select  select_list
From    table
Where   expr_operator 
	(select select_list  from table);
  1. 子查询(内查询)在主查询之前一次执行完成。
  2. 子查询的结果被主查询(外查询)使用。

注意事项

  • 子查询要包含在括号内
  • 将子查询放在比较条件的右侧

1.2、子查询案例

子查询案例
子查询案例

1、两次独立的查询

SELECT salary
FROM employees
WHERE last_name = 'Abel';

SELECT last_name,salary
FROM employees
WHERE salary > 11000;

2、自连接多表查询

SELECT e2.last_name,e2.salary
FROM employees e1,employees e2
WHERE e1.last_name = 'Abel'
AND e1.`salary` < e2.`salary`

3、子查询方式

SELECT last_name,salary
FROM employees
WHERE salary > (
		SELECT salary
		FROM employees
		WHERE last_name = 'Abel'
		);

二、单行子查询和多行子查询

我们按子查询的结果返回一条还是多条记录,将子查询分为单行子查询多行子查询

三、单行子查询

子查询的结果返回一条记录的SQL,归类于单行子查询。

3.1、单行比较操作符

操作符 含义
= equal to
> greater than
>= greater than or equal to
< less than
<= less than or equal to
<> not equal to

3.2、子查询中包含MIN聚合函数

返回公司工资最少的员工的last_name,job_id和salary。

SELECT last_name, job_id, salary
FROM   employees
WHERE  salary = 
            (SELECT MIN(salary)
            FROM   employees);

3.3、多个子查询条件

返回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.4、HAVING 中的子查询

首先执行子查询。向主查询中的HAVING 子句返回结果。
题目:查询最低工资大于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);

3.5、子查询中的空值问题

SELECT last_name, job_id
FROM   employees
WHERE  job_id =
                (SELECT job_id
                 FROM   employees
                 WHERE  last_name = 'Haas');

子查询结果为空:no rows selected

3.6、非法使用子查询

多行子查询使用单行比较符。

SELECT employee_id, last_name
FROM   employees
WHERE  salary =
                (SELECT   MIN(salary)
                 FROM     employees
                 GROUP BY department_id);

3.7、CASE中的子查询

在CASE表达式中使用单列子查询。
显式员工的employee_id,last_name和location。其中,若员工department_id与location_id为1800的department_id相同,则location为’Canada’,其余则为’USA’。

SELECT employee_id, last_name,
       (CASE department_id
        WHEN
             (SELECT department_id FROM departments
	      WHERE location_id = 1800)           
        THEN 'Canada' ELSE 'USA' END) location
FROM   employees;

四、多行子查询(集合比较子查询)

子查询的结果返回多条记录的SQL,归类于多行子查询。

4.1、多行比较操作符

操作符 含义
IN 等于列表中的任意一个
ANY 需要和单行比较操作符一起使用,和子查询返回的某一个值比较
ALL 需要和单行比较操作符一起使用,和子查询返回的所有值比较
SOME 实际上是ANY的别名,作用相同,一般常使用ANY

4.2、ANY 多表查询

返回其它job_id中比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";

4.3、ALL 多表查询

返回其它job_id中比job_id为‘IT_PROG’部门所有工资都低的员工的员工号、姓名、job_id以及salary。

Select employee_id,last_name,job_id,salary
From employees
WHERE salary < ALL 
			(SELECT salary
			From employees
			WHERE job_id="IT_PROG")
AND job_id <> "IT_PROG";

4.4、不成对比较 和 成对比较

查询与141号或174号员工的manager_id和department_id相同的其他员工的employee_id,manager_id,department_id。

4.4.1、实现方式1:不成对比较
SELECT  employee_id, manager_id, department_id
FROM    employees
WHERE   manager_id IN
		  (SELECT  manager_id
                   FROM    employees
                   WHERE   employee_id IN (174,141))
AND     department_id IN 
		  (SELECT  department_id
                   FROM    employees
                   WHERE   employee_id IN (174,141))
AND	employee_id NOT IN(174,141);
4.4.2、实现方式2:成对比较
SELECT	employee_id, manager_id, department_id
FROM	employees
WHERE  (manager_id, department_id) IN
                      (SELECT manager_id, department_id
                       FROM   employees
                       WHERE  employee_id IN (141,174))
AND	employee_id NOT IN (141,174);