W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
子查詢指的是 SELECT
查詢語句中嵌套了另一個或者多個 SELECT
語句,可以返回單行結(jié)果、多行結(jié)果或不返回結(jié)果。SELECT
語句的 FROM
子句中的子查詢也稱為內(nèi)聯(lián)視圖,SELECT
語句的 WHERE
子句中的子查詢也稱為嵌套子查詢。
子查詢可以分為相關(guān)子查詢和非相關(guān)子查詢。相關(guān)子查詢指該子查詢的執(zhí)行依賴了外部查詢的變量,這種子查詢通常會執(zhí)行多次。非相關(guān)子查詢指該子查詢的執(zhí)行不依賴外部查詢的變量,這種子查詢一般只需要計算一次。對于非相關(guān)子查詢與部分相關(guān)子查詢,可以通過改寫進行子查詢消除,實現(xiàn)嵌套子查詢的展開。
SELECT [ hint ] [ { { DISTINCT | UNIQUE } | ALL } ] select_list
FROM { table_reference | join_clause | ( join_clause ) }
[ , { table_reference | join_clause | (join_clause) } ]
[ where_clause ]
[ hierarchical_query_clause ]
[ group_by_clause ]
| subquery { UNION [ALL] | INTERSECT | MINUS } subquery [ { UNION [ALL] | INTERSECT | MINUS } subquery ]
| ( subquery ) [ order_by_clause ] [ row_limiting_clause ]
參數(shù) |
說明 |
---|---|
select_list |
查詢列表 |
subquery |
子查詢 |
hint |
注釋 |
table_reference |
要查詢的目標表 |
如果子查詢中的列與外層查詢中的列具有相同列名,必須在外層查詢中在重復(fù)列名前加上表名或使用別名。
當上層查詢引用到子查詢中相關(guān)列時,將執(zhí)行子查詢,上層查詢可以是SELECT
,UPDATE
或 DELETE
語句,各語句中使用子查詢方式:
定義要插入到 INSERT
或 CREATE TABLE
語句的目標表中的行集。
在 CREATE VIEW
或 CREATE MATERIALIZED VIEW
語句中定義要包含在視圖或物化視圖中的行集。
在 UPDATE
中定義要分配給現(xiàn)有行的一個或多個值。
在 WHERE
子句、HAVING
子句或 START WITH
中提供條件值。
定義包含查詢操作的表。
嵌套子查詢展開是數(shù)據(jù)庫的一種優(yōu)化策略,它把一些子查詢置于外層的父查詢中,其實質(zhì)是把某些子查詢轉(zhuǎn)化為等價的多表連接操作。這種策略帶來的一個明顯的好處是能夠有效利用訪問路徑、連接方法和連接順序,使查詢的層次盡可能的減少。
以下情況數(shù)據(jù)庫將進行嵌套子查詢的展開:
不相關(guān)的 IN
子查詢。
IN
和 EXISTS
中的相關(guān)子查詢不包含聚合函數(shù)或 GROUP BY
子句。可以通過 Hint UNNEST
控制是否展開嵌套子查詢。
以下語句創(chuàng)建了表 table_a和表 table_b,并向表中插入數(shù)據(jù):
CREATE TABLE table_a(PK INT, name VARCHAR(25));
INSERT INTO table_a VALUES(1,'??怂?#39;);
INSERT INTO table_a VALUES(2,'警察');
INSERT INTO table_a VALUES(3,'的士');
INSERT INTO table_a VALUES(4,'林肯');
INSERT INTO table_a VALUES(5,'亞利桑那州');
INSERT INTO table_a VALUES(6,'華盛頓');
INSERT INTO table_a VALUES(7,'戴爾');
INSERT INTO table_a VALUES(10,'朗訊');
CREATE TABLE table_b(PK INT, name VARCHAR(25));
INSERT INTO table_b VALUES(1,'??怂?#39;);
INSERT INTO table_b VALUES(2,'警察');
INSERT INTO table_b VALUES(3,'的士');
INSERT INTO table_b VALUES(6,'華盛頓');
INSERT INTO table_b VALUES(7,'戴爾');
INSERT INTO table_b VALUES(8,'微軟');
INSERT INTO table_b VALUES(9,'蘋果');
INSERT INTO table_b VALUES(11,'蘇格蘭威士忌');
沒有依賴關(guān)系的子查詢,執(zhí)行以下語句:
SELECT * FROM TABLE_A T1 WHERE T1.PK IN (SELECT T2.PK FROM TABLE_B T2);
查詢結(jié)果如下:
+------+-----------+
| PK | NAME |
+------+-----------+
| 1 | ??怂? |
| 2 | 警察 |
| 3 | 的士 |
| 6 | 華盛頓 |
| 7 | 戴爾 |
+------+-----------+
有依賴關(guān)系的子查詢,子查詢中用到了外層查詢變量 T1.PK,執(zhí)行以下語句:
SELECT * FROM TABLE_A T1 WHERE T1.PK IN (SELECT T2.PK FROM TABLE_B T2 WHERE T2.PK = T1.PK);
查詢結(jié)果如下:
+------+-----------+
| PK | NAME |
+------+-----------+
| 1 | ??怂? |
| 2 | 警察 |
| 3 | 的士 |
| 6 | 華盛頓 |
| 7 | 戴爾 |
+------+-----------+
有依賴關(guān)系的子查詢被展開改寫成連接,執(zhí)行以下語句:
EXPLAIN SELECT * FROM TABLE_A T1 WHERE T1.PK IN (SELECT T2.NAME FROM TABLE_B T2 WHERE T2.NAME = T1.NAME);
查詢結(jié)果如下:
+------------------------------------+
| Query Plan |
+------------------------------------+
=============================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
---------------------------------------------
|0 |HASH RIGHT SEMI JOIN| |8 |107 |
|1 | TABLE SCAN |T2 |8 |38 |
|2 | TABLE SCAN |T1 |8 |38 |
=============================================
Outputs & filters:
-------------------------------------
0 - output([T1.PK], [T1.NAME]), filter(nil),
equal_conds([T1.PK = T2.NAME], [T2.NAME = T1.NAME]), other_conds(nil)
1 - output([T2.NAME]), filter(nil),
access([T2.NAME]), partitions(p0)
2 - output([T1.NAME], [T1.PK]), filter(nil),
access([T1.NAME], [T1.PK]), partitions(p0)
+------------------------------------+
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: