OceanBase 子查詢

2021-06-28 10:31 更新

子查詢指的是 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ù)

參數(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 中提供條件值。

  • 定義包含查詢操作的表。

嵌套子查詢的展開(Unnesting of Nested Subqueries)

嵌套子查詢展開是數(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)
+------------------------------------+
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號