# 子查询表达式
子查询允许在一个查询中嵌套另一个查询，从而实现更复杂的数据查询和分析。
#### 子查询表达式
- EXISTS/NOT EXISTS 首先执行子查询，然后根据子查询的结果是否满足条件来决定是否继续执行主查询。如果子查询至少返回一行，则EXISTS结果就为"真"。如果子查询没有返回任何行， NOT EXISTS的结果是"真"。
  ![](https://support.huaweicloud.com/devg-911-dws/figure/zh-cn_image_0000001787832492.png "点击放大")
  语法：
  ```
  WHERE column_name EXISTS/NOT EXISTS (subquery)
  ```
  
- IN/NOT IN 用于测试某个给定的比较值是否存在于某一组值里。如果外层查询里的行与子查询返回的某一个行相匹配，那么IN的结果为"真"。如果外层查询中的行与子查询返回的所有行都不匹配，那么NOT IN的结果为"真"。
  ![](https://support.huaweicloud.com/devg-911-dws/figure/zh-cn_image_0000001834631725.png "点击放大")
  语法：
  ```
  WHERE column_name IN/NOT IN (subquery)
  ```
  
- ANY/SOME ANY表示子查询中的任何值都可以与外部查询中的值匹配。SOME与ANY相同，只是在语法上的差别。
  右边的子查询必须只返回一个字段。左边表达式使用operator对子查询结果的每一行进行一次计算和比较（=、\<\>、\<、\<=、\>、\>=），其结果必须是布尔值。如果至少获得一个真值，则ANY结果为"真"。如果全部获得假值，则结果是"假"（包括子查询没有返回任何行的情况）。
  ![](https://support.huaweicloud.com/devg-911-dws/figure/zh-cn_image_0000001787831724.png "点击放大")
  语法：
  ```
  WHERE column_name operator ANY/SOME (subquery)
  ```
  
- ALL 右边的子查询必须只返回一个字段。左边表达式使用operator对子查询结果的每一行进行一次计算和比较（=、\<\>、\<、\<=、\>、\>=），其结果必须是布尔值。如果全部获得真值，ALL结果为"真"（包括子查询没有返回任何行的情况）。如果至少获得一个假值，则结果是"假"。
  ![](https://support.huaweicloud.com/devg-911-dws/figure/zh-cn_image_0000001834631305.png "点击放大")
  语法：
  ```
  WHERE column_name operator ALL (subquery)
  ```
  表1ALL查询条件 
  | 条件                      | 描述                                       |
  |:---|:---|
  | column_name \> ALL(...)  | column_name列中的值必须大于要评估为true的集合中的最大值。     |
  | column_name \>= ALL(...)  | column_name列中的值必须大于或等于要评估为true的集合中的最大值。   |
  | column_name \< ALL(...)   | column_name列中的值必须小于要评估为true的集合中的最小值。     |
  | column_name \<= ALL(...) | column_name列中的值必须小于或等于要评估为true的集合中的最小值。 |
  | column_name \<\> ALL(...) | column_name列中的值不得等于要评估为true的集合中的任何值。       |
  | column_name = ALL(...)   | column_name列中的值必须等于要评估为true的集合中的任何值。     |
     
  
 
#### 示例
创建记录课程信息的表course，并插入数据：
```
CREATE TABLE course(cid VARCHAR(10) COMMENT 'No.course',cname VARCHAR(10) COMMENT 'course name',teid VARCHAR(10) COMMENT 'No.teacher');
INSERT INTO course VALUES('01' , 'course1' , '02'); 
INSERT INTO course VALUES('02' , 'course2' , '01'); 
INSERT INTO course VALUES('03' , 'course3' , '03');
```
创建教师表teacher，并插入数据：
```
CREATE TABLE teacher(teid VARCHAR(10) COMMENT '教师编号',tname VARCHAR(10) COMMENT '教师姓名');
INSERT INTO teacher VALUES('01' , 'teacher1'); 
INSERT INTO teacher VALUES('02' , 'teacher2');
INSERT INTO teacher VALUES('03' , 'teacher3');
INSERT INTO teacher VALUES('04' , 'teacher4');
```
- EXISTS/NOT EXISTS示例 查询在course表中的教师记录：
  ```
  SELECT * FROM teacher WHERE EXISTS (SELECT * FROM course WHERE course.teid = teacher.teid);
  ```
  ![](https://support.huaweicloud.com/devg-911-dws/figure/zh-cn_image_0000001814324420.png "点击放大")
  查询没有在course表中的教师记录：
  ```
  SELECT * FROM teacher WHERE NOT EXISTS (SELECT * FROM course WHERE course.teid = teacher.teid);
  ```
  ![](https://support.huaweicloud.com/devg-911-dws/figure/zh-cn_image_0000001861124593.png "点击放大")
  

- IN/NOT IN 示例 根据教师id匹配course表，查询在course表的教师信息：
  ```
  SELECT * FROM course WHERE teid IN (SELECT teid FROM teacher );
  ```
  ![](https://support.huaweicloud.com/devg-911-dws/figure/zh-cn_image_0000001814165292.png "点击放大")
  查询不在course表的教师信息：
  ```
  SELECT * FROM teacher WHERE teid NOT IN (SELECT teid FROM course );
  ```
  ![](https://support.huaweicloud.com/devg-911-dws/figure/zh-cn_image_0000001861005333.png "点击放大")
  

- ANY/SOME 示例 左侧主句与右侧子查询进行字段比对，获取需要的结果集：
  ```
  SELECT * FROM course WHERE teid < ANY (SELECT teid FROM teacher where teid<>'04');
  ```
  或
  ```
  SELECT * FROM course WHERE teid < some (SELECT teid FROM teacher where teid<>'04');
  ```
  ![](https://support.huaweicloud.com/devg-911-dws/figure/zh-cn_image_0000001814165600.png "点击放大")
  

- ALL示例 查询teid列中的值必须小于要评估为true的集合中的最小值：
  ```
  SELECT * FROM course WHERE teid < ALL(SELECT teid FROM teacher WHERE teid<>'01');
  ```
  ![](https://support.huaweicloud.com/devg-911-dws/figure/zh-cn_image_0000001814325508.png "点击放大")
  
 
#### 注意事项
- 禁止一条SQL语句中，出现重复子查询语句。
- 尽量少用标量子查询（标量子查询指结果为1个值，并且条件表达式为等值的子查询）。
- 避免在SELECT目标列中使用子查询，可能导致计划无法下推影响执行性能。
- 子查询嵌套深度建议不超过2层。由于子查询会带来临时表开销，过于复杂的查询应考虑从业务逻辑上进行优化。
子查询可以在 SELECT 语句中嵌套其他查询，从而实现更复杂的查询。子查询还可以在WHERE子句中使用其他查询的结果，从而更好地过滤数据。但是子查询可能会导致查询性能问题和代码难阅读和理解。 所以在DWS数据库中使用SQL子查询时，请结合实际业务情况进行操作。
