
# Join顺序的Hint
#### 功能描述
指明join的顺序，包括内外表顺序。
#### 语法格式
- 单层圆括号()，仅指定join顺序，不指定内外表顺序。
```
leading(join_table_list) 
leading(@block_name join_table_list)
```
- 双层圆括号(())，同时指定join顺序和内外表顺序，内外表顺序仅在最外层生效。
```
leading((join_table_list)) 
leading(@block_name (join_table_list))
```
- 单层方括号\[\]，同时指定\[\]这层的join顺序和内外表顺序。
```
leading[join_table_list]
leading[@block_name join_table_list]
```
- 单层圆括号()和单层方括号\[\]混合使用，同时指定join顺序和任意层内外表顺序。圆括号()这一层只指定join顺序，不指定内外表顺序，方括号\[\]这一层同时指定join顺序和内外表顺序。
```
leading(join_table_list1 [join_table_list2])
leading[join_table_list1 [join_table_list2]]
leading[join_table_list1 (join_table_list2)]
leading(@block_name join_table_list1 [join_table_list2])
leading[@block_name join_table_list1 [join_table_list2]]
leading[@block_name join_table_list1 (join_table_list2)]
```
![](https://support.huaweicloud.com/devg-fabric/public_sys-resources/notice_3.0-zh-cn.png)
单层方括号\[\]可以和单层圆括号()混合使用，指定任意层的内外表顺序。不支持单层\[\]和双层(())一起使用。
#### 参数说明
- **join_table_list**
  为表示表join顺序的hint字符串，可以包含当前层的任意个表（别名），或对于子查询提升的场景，也可以包含子查询的hint别名，同时任意表可以使用括号指定优先级，表之间使用空格分隔。
  join table list中指定的表需要满足以下要求，否则会报语义错误：
  - list中的表必须在当前层或提升的子查询中存在。
  
  - list中的表在当前层或提升的子查询中必须是唯一的。如果不唯一，需要使用不同的别名进行区分。
  
  - 同一个表只能在list里出现一次。
  
  - 如果表存在别名，则list中的表需要使用别名。
   
  ![](https://support.huaweicloud.com/devg-fabric/public_sys-resources/note_3.0-zh-cn.png)
  - 表的语法格式如下： \[schema.\]table\[@block_name\]
    表名可以带schema，也可以带所在子查询语句块提升前的block_name。子查询语句块在优化器进行优化重写时发生提升，则该block_name会与leading中block_name不同。
    
  
  - 表如果存在别名，优先使用别名来表示该表。
    
 
- **block_name**
  语句块的block_name。表示该hint在block_name对应的子查询语句块中生效。
  ![](https://support.huaweicloud.com/devg-fabric/public_sys-resources/notice_3.0-zh-cn.png)
  - 默认为语句生成block_name。
  
  
  
  - CN轻量化不生成block_name。
  
  
  
  - create table as select、select into、select、insert、update、delete、merge语句生成block_name。
  
  
  
  - block_name的命名规则：
    - 为select、insert、update、delete、merge语句自动生成blockname，block_name的命名格式分别为sel$n、ins$n、upd$n、del$n、mer$n，n从1开始计数，不同类型语句之间，计数不累加，同一类型语句之间计数累加。 例如：
      ```
      INSERT INTO t SELECT * FROM t1 WHERE a1 IN (select * from t2);
      ```
      --------sel$2-------
      -----------------------sel$1----------------------
      --------------------------------ins$1---------------------------
      
    
    - 在优化器之前递归为每个语句块分配block_name。
      首先为当前语句块根据语句类型分配block_name，然后按照下面的顺序进行遍历，并为其中的语句块分配block_name：
      1. 遍历目标列
      
      2. 遍历merge语句的源表中的目标列
      
      3. 遍历merge语句中的action（update/insert）
      
      4. 遍历returning子句
      
      5. 遍历from中的join条件和where条件（join条件优先于where条件）
      
      6. 如果是集合操作，遍历集合的各个分支（union/intersect/except）
      
      7. 遍历having子句
      
      8. 遍历limit offset子句
      
      9. 遍历limit count子句
      
      10. 遍历cte
      
      11. 遍历from后的表
      
      12. 遍历upsert子句
        
    
    - 在优化器的重写阶段，由于fulljoin、cte inline、物化视图重写、inlist2join、or转换、multi count(distinct)、magicset、lazyagg、子查询/子链接提升等重写优化，都会构造新的子查询，此时会对新构造的子查询也应用上面分配block_name的递归处理，block_name的编号计数在之前的基础上进行累加。
    
    - 优化器重写阶段，发生子查询提升时，内层子查询中的表被提升到外层查询中，内层子查询被消除。此时，被提升的表可能会和外层查询中的表同名，所以在表中记录其原本所属block_name来区分来自不同查询块中的两个相同表。
     
    
例如：
leading(t1 t2 t3 t4 t5)表示：t1、t2、t3、t4、t5先join，五表join顺序及内外表不限。
leading((t1 t2 t3 t4 t5))表示：t1和t2先join，t2做内表；再和t3 join，t3做内表；再和t4 join，t4做内表；再和t5 join，t5做内表。
leading(t1 (t2 t3 t4) t5)表示：t2、t3、t4先join，内外表不限；再和t1, t5 join，内外表不限。
leading((t1 (t2 t3 t4) t5))表示：t2、t3、t4先join，内外表不限；在最外层，t1再和t2、t3、t4的join表join，t1为外表，再和t5 join，t5为内表。
leading((t1 (t2 t3) t4 t5)) leading((t3 t2))表示：t2、t3先join，t2做内表；然后再和t1 join，t2、t3的join表做内表；然后再依次跟t4、t5做join，t4、t5做内表。
leading\[t1 \[t2 t3\]\]等价于leading((t1 (t2 t3))) leading((t2 t3))。
leading(t1 \[t2 t3\])等价于leading(t1 t2 t3) leading((t2 t3))。
leading\[@sel$1 t1@sel$1 \[t2@sel$2 t3@sel$2\]\]表示：t2、t3位于子查询中，子查询被提升后，和t1进行join，其表示先t2和t3 join，t2为外表，t3为内表；然后再和t1 join，t1为外表，t2, t3的join表做内表。
#### 示例
对[示例](https://support.huaweicloud.com/devg-fabric/dataartsfabric_sql_04_0098.html#ZH-CN_TOPIC_0000002482710193__zh-cn_topic_0000001658028034_section671421102912)中原语句使用如下hint:
```
explain
select /*+ leading((((((store_sales store) promotion) item) customer) ad2) store_returns) leading((store store_sales))*/ i_product_name product_name ...
```
该hint表示：表之间的join关系是：store_sales和store先join， store_sales做内表，然后依次跟promotion, item, customer, ad2, store_returns做join。生成计划如下所示：
![](https://support.huaweicloud.com/devg-fabric/figure/zh-cn_image_0000002449670816.png "点击放大")
图中计划顶端warning的提示详见[Hint的错误、冲突及告警](https://support.huaweicloud.com/devg-fabric/dataartsfabric_sql_04_0112.html)的说明。
