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;

執行上面查詢語句,得到以下結果:

在此範例中,外部查詢是:

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相關子查詢以及如何將其應用於形成複雜查詢。