1. 程式人生 > >SQL SELECT(複雜查詢)之 自連線 & 子查詢 解析

SQL SELECT(複雜查詢)之 自連線 & 子查詢 解析

SQL SELECT(複雜查詢)之 自連線 & 子查詢 解析

一、自連線

概念:把一張表 當做多個表使用

語法:

select ...
from 表 a(別名)
join 表 b(別名)

on a.欄位=b.欄位

注意:

自連線也可以是 內連線也可以是外連線
自己與一張與自己完全一樣的從表建立關係 進行連線查詢

以下舉例所用表

employees表:欄位如下

employee_id, first_name, last_name, email, phone_number

job_id, salary, commission_pct, manage_id, department_id

案例: xx員工 為 xx上司 工作

分析:

employees表:欄位如下

employee_id, first_name, last_name, email, phone_number

job_id, salary, commission_pct, manage_id, department_id

manage_id 是員工id為emplo_id的領導者id 其對應的一條記錄也是

employees表中的一條普通員工記錄

/*
進一步分析:

1.相當於查詢員工名和上司名
2.將自己(employees表)當做兩個表, m和e

*/
#分析1
//相當於從employee表中查詢 經過匹配後 得到這個員工的領導  
   manager_id 再把它從這個表中查出來

SELECT e.`first_name` 員工名,m.`first_name` 老闆名
FROM employees e
JOIN employees m  ON e.`manager_id`=m.`employee_id`

#分析2 通過自己與自己內連線 跟自連線 一樣
SELECT CONCAT(e.`first_name`,' work for ',m.`first_name`)  info
FROM employees e
JOIN employees m  ON e.`manager_id`=m.`employee_id`

二、子查詢

(一)子查詢

分類:

單行子查詢: 子查詢的結果集是一行

多行子查詢: 子查詢的結果集是多行

注意事項:
    子查詢要包含在括號內。

    將子查詢放在比較條件的右側。

    單行操作符對應單行子查詢,多行操作符對應多行子查詢。
單行操作符:
    > < >= <= = <>
多行操作符:
    in(重點)、any(任意一個)、all(所有的)
    not in

1、單行子查詢

 比較的物件是唯一的一個而不是一個範圍集合

1.案例:誰的工資比 Abel 高?

/*
    分析1: 求出Abel的工資
    分析2: 篩選employees表,判斷 salary > Abel的工資
*/

求出Abel的工資,得到一個值
SELECT salary FROM employees WHERE last_name = 'Abel';

篩選employees表,判斷 salary > Abel的工資
SELECT * FROM employees WHERE salary>11000;


結合以上兩部分析將第一個分析所得結果作為被比較的條件物件

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

2.案例:返回job_id與141號員工相同,salary比143號員工多的員工

    姓名,job_id 和工資

     /*
     分析1:先查詢 141 號員工的job_id
           以及 143號員工的salary
     */

1》先查詢 141 號員工的job_id
   以及 143號員工的salary


SELECT job_id 
FROM employees 
WHERE employee_id = 141

SELECT salary 
FROM employees 
WHERE employee_id = 143

2》結合以上兩部將其作為被比較的條件物件篩選指定的員工

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 子查詢中使用了組函式。

以下舉例所用表

employees表:欄位如下

employee_id, first_name, last_name, email, phone_number

job_id, salary, commission_pct, manage_id, department_id

案例 返回工資最少的員工的last_name,job_id和salary

SELECT last_name,job_id,salary 
FROM employees
WHERE salary=(

    //把如下語句獲取的值作為salary比較的條件物件
    SELECT MIN(salary) FROM employees
);

SELECT * FROM employees;//檢視結果有沒有改變

4 子查詢中用到了having

案例:查詢最低工資大於50號部門最低工資的部門id和其最低工資

/*
    分析1:先查詢50號部門的最低工資
    分析2:每個部門的部門id和其最低工資
    分析3:篩選看哪個部門的最低工資大於分析1的結果

*/
#分析1
SELECT MIN(salary) 
FROM employees
WHERE department_id=50

#分析2
SELECT MIN(salary) ,department_id
FROM employees
GROUP BY department_id

#分析3

SELECT MIN(salary) ,department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
    SELECT MIN(salary) 
    FROM employees
    WHERE department_id=50

);

非法使用單行子查詢,其實就是 子查詢結果集中返回的是多行
SELECT MIN(salary) ,department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
SELECT salary
FROM employees
WHERE department_id>50//返回的是多個值物件

);

單行子查詢的結果集中出現 null的問題

SELECT MIN(salary) ,department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
    SELECT salary 
    FROM employees
    WHERE department_id>300 //結果為null

);

單行子查詢的結果集多列的問題

SELECT MIN(salary) ,department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(  //到這一步 用於比較的MIN(salary)有很多個 不
    SELECT MIN(salary),department_id 
    FROM employees
    WHERE department_id=50  //50號部門最低工資

);

二、多行子查詢
1.題目:

返回其它部門中比job_id為‘IT_PROG’部門任一工資低的員工的員

工號、姓名、job_id 以及salary

提示:比最高工資低 就行

     /*
     分析1: 先查詢 job_id為‘IT_PROG’部門任一工資
     分析2: 查詢員工號、姓名、job_id 以及salary  比分析1的 結果中任意一個都低的

     */

     1》. 先查詢 job_id為‘IT_PROG’部門任一工資

     SELECT salary 
     FROM employees
     WHERE job_id = 'IT_PROG'


     2 》查詢員工號、姓名、job_id 以及salary  比分析1的 結果中任意一個都低的

     SELECT employee_id,last_name,job_id,salary
     FROM employees
     WHERE salary<ANY(
            SELECT salary 
         FROM employees
         WHERE job_id = 'IT_PROG'

     )

2.題目:返回其它部門中比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'

     )

3.題目:返回其它部門中工資和 job_id為‘IT_PROG’部門的隨便一個工資 相同 的員工

SELECT employee_id,last_name,job_id,salary
     FROM employees
     WHERE salary NOT IN(
            SELECT salary 
         FROM employees
         WHERE job_id = 'IT_PROG'
     )

語法:

in(值1,值2,值3)
salary =值1 or salary=值2 or salary=值3