个人技术分享

一. 定义

with A as (select * from class)

也就是将重复用到的大批量 的SQL语句,放到with as 中,加一个别名,在后面用到的时候就可以直接用。对于大批量的SQL数据,起到优化的作用。

with子句的返回结果存到用户的临时表空间中,只做一次查询,反复使用,提高效率。

 

二. 用法

  1. with子句只能被select查询块引用
  2. 在同级select前有多个查询定义的时候,第1个用with,后面的不用with,并且用逗号隔开。
  3. 最后一个with 子句与下面的查询之间不能有逗号,只通过右括号分割,with 子句的查询必须用括号括起来。

-- 针对一个别名
-- –相当于建了个e临时表

with e as (select * from scott.emp e where e.empno=7499)
select * from e;

-- –针对多个别名,相当于建了e、d临时表

with
e as (select * from scott.emp),
d as (select * from scott.dept)
select * from e, d where e.deptno = d.deptno;

 

三. 解析


<dependency>  
  <groupId>com.github.jsqlparser</groupId>  
  <artifactId>jsqlparser</artifactId>  
  <version>4.9</version>  
</dependency>

官网文档:

https://jsqlparser.github.io/JSqlParser/usage.html#parse-a-sql-statements

//去除 with语法下的别名
private static Set<String> removeWithAlias(String sql, Set<String> tables) {  
    if (sql.contains("with ")) {  
        PlainSelect select = null;  
        try {  
            select = (PlainSelect) CCJSqlParserUtil.parse(sql);  
            List<WithItem> withItemsList = select.getWithItemsList();  
            List<String> withAlias = withItemsList.stream()  
                    .map(withItem -> withItem.getAlias().getName())  
                    .collect(Collectors.toList());  
            return tables.stream().filter(t -> !withAlias.contains(t))  
                    .collect(Collectors.toSet());  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
    return tables;  
}