testbook

WITH...AS

当子查询嵌套层数较多,语句会难以阅读和维护。我们可以通过用WITH...AS定义公共表表达式(CTE)来简化查询,提高可阅读性和易维护性。
语法

WITH cte_name AS (select_statement) sql_containing_cte_name
说明
  • cte_name是公共表表达式的名字
  • select_statement是一个完整的SELECT语句
  • sql_containing_cte_name是包含了刚刚定义的公共表表达式的SQL语句,注意,定义了一个CTE以后必须马上使用,否则这个CTE定义将失效。
  • 举例
    [$host] transwarp> WITH nv AS (SELECT name FROM user_info JOIN transactions ON acc_num = acc_num) SELECT DISTINCT name FROM nv;
    邱坤
    管淑艳
    李韩瑶
    潘营泽
    祝韩恒
    魏向卉
    马从筠
    华微
    
    在WITH...AS连续定义多个CTE
    用户可以通过一次WITH定义多个CTE,中间用逗号连接:
    WITH cte_1 AS (select_statement_1),
         cte_2 AS (select_statement_2),
         cte_3 AS (select_statement_3),
         ...
         sql_containing_all_defined_ctes
    
    说明
  • 所有定义的cte必须都马上使用。
  • 后定义的cte可以引用已经定义的cte。
  • 举例 下例查询所有个人平均交易额大于所有平均交易额的用户名字
    [$host] transwarp> SELECT name FROM user_info JOIN (SELECT transactions.acc_num, avg(price\*amount) avg_trans FROM transactions GROUP BY transactions.acc_num) personal_avg ON user_info.acc_num = personal_avg.acc_num WHERE avg_trans > (SELECT avg(price\*amount) FROM transactions);
    祝韩恒
    华微
    李韩瑶
    管淑艳
    
    用WITH...AS改写:
    [$host] transwarp> WITH
                       personal_avg AS (SELECT transactions.acc_num, avg(price*amount)avg_trans FROM transactions GROUP BY transactions.acc_num),
                       namelist AS (SELECT name FROM user_info JOIN personal_avg ON user_info.acc_num = personal_avg.acc_num WHERE avg_trans > (SELECT avg(price*amount) FROM transactions))
                       SELECT * FROM namelist;
    祝韩恒
    华微
    李韩瑶
    管淑艳