SQL相关子查询

在本教程中,您将了解SQL相关子查询,它是使用外部查询中的值的子查询。

1. SQL相关子查询简介

下面通过一个例子开始。

请参阅示例数据库中的employees表:

desc employees;
+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| employee_id   | int(11)      | NO   | PRI | NULL    | auto_increment |
| first_name    | varchar(20)  | YES  |     | NULL    |                |
| last_name     | varchar(25)  | NO   |     | NULL    |                |
| email         | varchar(100) | NO   |     | NULL    |                |
| phone_number  | varchar(20)  | YES  |     | NULL    |                |
| hire_date     | date         | NO   |     | NULL    |                |
| job_id        | int(11)      | NO   | MUL | NULL    |                |
| salary        | decimal(8,2) | NO   |     | NULL    |                |
| manager_id    | int(11)      | YES  | MUL | NULL    |                |
| department_id | int(11)      | YES  | MUL | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+
10 rows in set

以下查询查找薪水大于所有员工平均薪水的员工:

SELECT 
    employee_id, 
    first_name, 
    last_name, 
    salary
FROM
    employees
WHERE
    salary > (SELECT 
            AVG(salary)
        FROM
            employees);

执行上面查询语句,得到以下结果:

+-------------+------------+-----------+--------+
| employee_id | first_name | last_name | salary |
+-------------+------------+-----------+--------+
|         100 | Steven     | Lee       | 24000  |
|         101 | Neena      | Wong      | 17000  |
|         102 | Lex        | Liang     | 17000  |
|         103 | Alexander  | Lee       | 9000   |
|         108 | Nancy      | Chen      | 12000  |
|         109 | Daniel     | Chen      | 9000   |
|         110 | John       | Chen      | 8200   |
|         114 | Avg        | Su        | 11000  |
|         121 | Max        | Han       | 8200   |
|         145 | John       | Liu       | 14000  |
|         146 | Karen      | Liu       | 13500  |
|         176 | Jonathon   | Yang      | 8600   |
|         177 | Jack       | Yang      | 8400   |
|         201 | Michael    | Zhou      | 13000  |
|         204 | Hermann    | Wu        | 10000  |
|         205 | Shelley    | Wu        | 12000  |
|         206 | William    | Wu        | 8300   |
+-------------+------------+-----------+--------+
17 rows in set

在此示例中,子查询在WHERE子句中使用。可以从此查询中看到一些要点:

首先,可以执行子查询,此子查询独立返回所有员工的平均工资。

SELECT 
    AVG(salary)
FROM
    employees;

其次,数据库系统只需要对子查询进行一次评估。

第三,外部查询使用从子查询返回的结果。 外部查询依赖于子查询的值。 但是,子查询不依赖于外部查询。 有时,我们称这个子查询是一个普通的子查询。

与普通子查询不同,相关子查询是使用外部查询中的值的子查询。 此外,可以针对外部查询选择的每一行评估相关子查询一次。 因此,使用相关子查询的查询可能很慢。

相关子查询也称为重复子查询或同步子查询。

2. SQL相关的子查询示例

让我们看一下相关子查询的一些例子,以便更好地理解它们。

2.1. WHERE子句示例中的SQL相关子查询

以下查询查找薪水高于其部门员工平均薪水的所有员工:

SELECT 
    employee_id,first_name,last_name,salary,department_id
FROM
    employees e
WHERE
    salary > (SELECT 
            AVG(salary)
        FROM
            employees
        WHERE
            department_id = e.department_id)
ORDER BY 
    department_id ,  first_name , last_name;

执行上面查询语句,得到以下结果:

《SQL相关子查询》

在此示例中,外部查询是:

SELECT 
    employee_id, 
    first_name, 
    last_name, 
    salary, 
    department_id
FROM
    employees e
WHERE
    salary >
...

相关子查询是:

SELECT
    AVG( list_price )
FROM
    products
WHERE
    category_id = p.category_id

对于每个员工,数据库系统必须执行一次相关子查询,以计算当前员工部门中员工的平均工资。

2.2. SELECT子句示例中的SQL相关子查询

以下查询返回员工及其部门中所有员工的平均薪水:

SELECT 
    employee_id,
    first_name,
    last_name,
    department_name,
    salary,
    (SELECT 
            ROUND(AVG(salary),0)
        FROM
            employees
        WHERE
            department_id = e.department_id) avg_salary_in_department
FROM
    employees e
        INNER JOIN
    departments d ON d.department_id = e.department_id
ORDER BY 
    department_name, 
    first_name, 
    last_name;

执行上面查询语句,得到以下结果:

+-------------+------------+-----------+-----------------+--------+--------------------------+
| employee_id | first_name | last_name | department_name | salary | avg_salary_in_department |
+-------------+------------+-----------+-----------------+--------+--------------------------+
|         103 | Alexander  | Lee       | IT              | 9000   | 5760                     |
|         104 | Bruce      | Wong      | IT              | 6000   | 5760                     |
|         105 | David      | Liang     | IT              | 4800   | 5760                     |
|         107 | Diana      | Chen      | IT              | 4200   | 5760                     |
|         106 | Valli      | Chen      | IT              | 4800   | 5760                     |
|         203 | Susan      | Zhou      | 人力资源        | 6500   | 6500                     |
|         205 | Shelley    | Wu        | 会计            | 12000  | 10150                    |
... ...
|         119 | Karen      | Zhang     | 采购            | 2500   | 4150                     |
|         116 | Shelli     | Zhang     | 采购            | 2900   | 4150                     |
|         117 | Sigal      | Zhang     | 采购            | 2800   | 4150                     |
|         179 | Charles    | Yang      | 销售            | 6200   | 9617                     |
|         177 | Jack       | Yang      | 销售            | 8400   | 9617                     |
|         145 | John       | Liu       | 销售            | 14000  | 9617                     |
|         176 | Jonathon   | Yang      | 销售            | 8600   | 9617                     |
|         146 | Karen      | Liu       | 销售            | 13500  | 9617                     |
|         178 | Kimberely  | Yang      | 销售            | 7000   | 9617                     |
+-------------+------------+-----------+-----------------+--------+--------------------------+
40 rows in set

对于每个员工,数据库系统必须执行一次相关子查询,以计算员工部门的平均工资。

2.3. SQL将子查询与EXISTS运算符示例相关联

经常使用与EXISTS运算符相关的子查询。 例如,以下查询返回没有依赖项的所有员工:

SELECT 
    employee_id, first_name, last_name
FROM
    employees e
WHERE
    NOT EXISTS( SELECT 
            *
        FROM
            dependents d
        WHERE
            d.employee_id = e.employee_id)
ORDER BY first_name , last_name;

执行上面查询语句,得到以下结果:
《SQL相关子查询》

在本教程中,您了解了SQL相关子查询以及如何将其应用于形成复杂查询。

        原文作者:SQL教程
        原文地址: https://www.yiibai.com/sql/sql-correlated-subquery.html
        本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
    点赞