---
# System prepended metadata

title: Ch02 集合運算與巢狀查詢
tags: [school]

---

# Ch02 集合運算與巢狀查詢
## 01_集合運算查詢
* 集合運算子
1. **交集**(Intersection)<SQL Server有支援,但MySQL沒有>
2. **聯集**(Union)
3. **差集**(Difference)<SQL Server有支援,但MySQL沒有>
 
* <font color="#f00">**條件**</font> : 
 (1)兩資料表的**資料行(欄位)個數必須相同**
(2)相對應的資料行(欄位)之**資料型態必須一致**

### 交集 
* 兩個關聯式中**都有出現**的值組(記錄)組合在一起成為新的關聯式
```sql=
SELECT *
FROM 關聯表R1 Intersect 關聯表R2
```
![](https://i.imgur.com/EjXYn1X.png)

### 聯集
* 新的關聯表R3中的記錄為原來**兩關聯表的所有記錄**，若有**重複的記錄**，則只會**出現一次**。
```sql=
SELECT *
FROM 關聯表R1 Union 關聯表R2
```
![](https://i.imgur.com/c0ZPWBp.png)

### 差集 
* 一個關聯表R1中的記錄**減去另一個關聯表**R2的記錄，形成新的關聯表R3的記錄。
```sql=
SELECT *
FROM 關聯表R1 Except 關聯表R2
```
![](https://i.imgur.com/XeYzfSz.png)

## 02_巢狀查詢和子查詢
* <font color="#f00">**定義**</font> :在SELECT敘述中，再**嵌入另一個SELECT敘述**，稱為巢狀查詢。
* <font color="#f00">**介紹**</font> : **外部**的SELECT敘述稱為**主查詢**，**內嵌**的SELECT敘述為**子查詢**。
*  子查詢可以出現在：
◆ Where子句中，作為篩選條件。
◆ From子句中，作為一個臨時表使用。
◆ Select list中，作為一個字段值來返回。

* WHERE子句子查詢
依子查詢的結果為單值或多值，使用不同的運算符號
![](https://i.imgur.com/S3bvWLc.png)
> **單值子查詢** ：子查詢的返回結果**只有一個數值**。
**多值子查詢** ：子查詢的返回結果是 (同一個欄位) **多個數值**。

 
*  WHERE 子句=子查詢 
>找出選修「資料庫系統」的學生學號及姓名。
>> 單值子查詢
```SQL=
SELECT A.學號, A.姓名
FROM 學生資料表 AS A , 選課資料表 AS B,課程資料表 AS C
WHERE A.學號=B.學號 AND B.課號=
(
    SELECT C.課號 
    WHERE 課名='資料庫系統'
);
```
* WHERE 子句>子查詢
>  找出操行成績大於平均操行成績的學生。
>> 單值子查詢
```SQL=
SELECT A.學號 , A.姓名 ,B.操行成績 
FROM 學生資料表 AS A, 學務處資料表 AS B
WHERE A.學號 = B.學號 
AND B.操行成績>
(SELECT AVG(操行成績) FROM 學務處資料表)
```

* Where子句 - 主查詢交叉比對子查詢
>找出選修「課號為C005」的學生學號及姓名
>> 單值子查詢
```SQL=
SELECT A.學號, A.姓名
FROM 學生資料表 AS A
WHERE A.學號 = (SELECT 學號
FROM 選課資料表 AS B
WHERE A.學號 = B.學號
AND B.課號='C005');
```
* Where子句IN子查詢 
> 找出有修「資料」開頭的課程之同學
>> 多值子查詢
```SQL=
SELECT Distinct A.學號, A.姓名
FROM 學生資料表 AS A, 選課資料表 AS B
WHERE A.學號 = B.學號
AND B.課號 IN (SELECT C.課號
FROM 課程資料表 AS C
WHERE 課名 LIKE '資料%');
```

* Where子句ALL子查詢
> 找出「甲班成績單」中有那些同學的「成績」比「乙班成績
單」中所有同學的「成績」高
>> 有些MySQL版本不支援
```SQL=
SELECT * FROM 甲班成績單
WHERE 成績 > ALL (SELECT 成績 FROM 乙班成績單)
```
* Where子句ANY子查詢
> 找出「甲班成績單」中有那些同學的「成績」比「乙班成績
單」中任何同學的「成績」低
>> 有些MySQL版本不支援
```SQL= 
SELECT * FROM 甲班成績單
WHERE 成績 < Any (SELECT 成績 FROM 乙班成績單)
```

* Where子句EXISTS子查詢
> 找出有修「資料」開頭的課程之同學
>> 布林子查詢
```SQL=
SELECT Distinct A.學號, A.姓名
FROM 學生資料表 AS A, 選課資料表 AS B
WHERE A.學號 = B.學號
AND EXISTS (SELECT C.課號
FROM 課程資料表 AS C
WHERE 課名 = '資料庫系統');
```

* From 子句子查詢
> 子查詢出現在From子句中，子查詢結果為一個表格（子表、臨時表）。
```sql=
SELECT A.課號, A.學號, A.成績, B.平均分
FROM 選課資料表 AS A INNER Join
(SELECT 課號, AVG(成績) AS 平均分
FROM 選課資料表
GROUP BY 課號) AS B
ON (A.課號 = B.課號)
ORDER BY A.課號, A.學號
```

* Select list 子查詢
> 請列出教職員「編號，姓名」及其主管的「主管代碼、主管姓名」
```sql=
SELECT 編號, 姓名, 主管 AS 主管編號,
(Select 姓名 from 教職員資料表 AS B
where A.主管=B.編號) AS 主管姓名
FROM 教職員資料表 AS A;
```