更新时间:2020-04-08 18:22
子查询指的是 SELECT
查询语句中嵌套了另一个或者多个 SELECT
语句,可以返回单行结果、多行结果或不返回结果。SELECT
语句的 FROM
子句中的子查询也称为内联视图。您可以在嵌入式视图中嵌套任意数量的子查询。SELECT
语句的 WHERE
子句中的子查询也称为嵌套子查询。
子查询可以分成有依赖关系的子查询和没有依赖关系的子查询。有依赖关系的子查询是指该子查询的执行依赖了外部查询的变量,所以这种子查询通常会被计算多次。没有依赖关系的子查询是指该子查询的执行不依赖外部查询的变量,这种子查询一般只需要计算一次。子查询按类型可分为:
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 ]
参数 | 说明 |
---|---|
select_list | 查询列表。 |
subquery | 子查询。 |
hint | 注释。 |
table_reference | 要查询的目标表。 |
如果子查询中的列与包含语句中的列具有相同的名称,则必须在包含语句中对表列的任何引用之前加上表名或别名。您可以将子查询中的列与表、视图或实例视图的名称或别名进行限定。
当嵌套子查询引用来自引用到子查询上方一个级别的父语句的表的列时,OceanBase 执行相关的子查询。父语句可以是嵌套子查询的选择、更新或删除语句。Hint 可以选择重写查询作为连接,或者使用其他技术来制定语义等效的查询。OceanBase 通过查看子查询中命名的表,然后在父语句中命名的表中查找子查询中的不合格列,从而解析子查询中的不合格列。
当嵌套的子查询引用表中的列时,OceanBase 会执行相关的子查询,该表引用了子查询上一级的父语句。父查询语句可以是子查询嵌套在其中的 SELECT
,UPDATE
或 DELETE
语句。从概念上讲,对关联的子查询对父查询语句处理的每一行都进行一次评估。但是,Hint 可以选择将查询重写为联接,也可以使用其他某种技术来制定语义上等效的查询。OceanBase 通过在子查询中命名的表然后在父语句中命名的表中查找子查询中的非限定列。相关子查询回答一个多部分问题,其答案取决于父语句处理的每一行中的值。
以下语句会用到子查询:
INSERT
或 CREATE TABLE
语句的目标表中的行集。CREATE VIEW
或 CREATE MATERIALIZED VIEW
语句中定义要包含在视图或实例化视图中的行集。UPDATE
中定义要分配给现有行的一个或多个值。WHERE
子句,HAVING
子句或 START WITH
中提供条件值 SELECT
、UPDATE
和 DELETE
语句的子句。嵌套子查询展开是数据库的一种优化策略,它把一些子查询置于外层的父查询中,其实质是把某些子查询转化为等价的多表连接操作。这种策略带来的一个明显的好处是写访问路径、连接方法和连接顺序可能被有效的利用,使得查询语句的层次尽可能的减少。
Hint 将自动取消以下嵌套子查询:
IN
子查询。IN
和 EXISTS
相关子查询不包含聚合函数或 GROUP BY
子句。HASH_AJ
来取消嵌套不相关的 NOT IN
子查询中的 MERGE_AJ
提示。UNNEST
提示来取消嵌套其他子查询。您可以使用 OceanBase 客户端远程访问 OceanBase 分布式数据库里的数据。
以下语句创建了表 table_a和表 table_b,并向表中插入数据:
CREATE TABLE table_a(PK INT, name VARCHAR(25));
INSERT INTO table_a VALUES(1,'福克斯');
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,'福克斯');
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,'苏格兰威士忌');
没有依赖关系的子查询,执行以下语句:
SELECT * FROM TABLE_A T1 WHERE T1.PK IN (SELECT T2.PK FROM TABLE_B T2);
查询结果如下:
+------+-----------+
| PK | NAME |
+------+-----------+
| 1 | 福克斯 |
| 2 | 警察 |
| 3 | 的士 |
| 6 | 华盛顿 |
| 7 | 戴尔 |
+------+-----------+
有依赖关系的子查询,子查询中用到了外层查询变量 T1.PK,执行以下语句:
SELECT * FROM TABLE_A T1 WHERE T1.PK IN (SELECT T2.PK FROM TABLE_B T2 WHERE T2.PK = T1.PK);
查询结果如下:
+------+-----------+
| PK | NAME |
+------+-----------+
| 1 | 福克斯 |
| 2 | 警察 |
| 3 | 的士 |
| 6 | 华盛顿 |
| 7 | 戴尔 |
+------+-----------+
有依赖关系的子查询被展开改写成连接,执行以下语句:
EXPLAIN SELECT * FROM TABLE_A T1 WHERE T1.PK IN (SELECT T2.NAME FROM TABLE_B T2 WHERE T2.NAME = T1.NAME);
查询结果如下:
+------------------------------------+
| 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)
+------------------------------------+
在文档使用中是否遇到以下问题
更多建议
匿名提交