• SQL 公用表表达式(CTE)


    1、概念

    公用表表达式(Common Table Expression)是SQL SERVER 2005版本之后引入的一个特性.CTE可以看作是一个临时的结果集,可以在接下来的一个SELECT,INSERT,UPDATE,DELETE,MERGE语句中被多次引用。使用公用表达式可以让语句更加清晰简练.

         除此之外,根据微软对CTE好处的描述,可以归结为四点:

    •      可以定义递归公用表表达式(CTE)
    •      当不需要将结果集作为视图被多个地方引用时,CTE可以使其更加简洁
    •     GROUP BY语句可以直接作用于子查询所得的标量列
    •     可以在一个语句中多次引用公用表表达式(CTE)

    2、数据

    姓名    课程    分数
    张三    语文    74
    张三    数学    83
    张三    物理    93
    李四    语文    74
    李四    数学    84
    李四    物理    94

    3、嵌套的查询语句

    select * from tb where 分数 in (select 分数 from tb where 分数>90)

    上面的查询语句使用了一个子查询。虽然这条SQL语句并不复杂,但如果嵌套的层次过多,会使SQL语句非常难以阅读和维护。

    因此,也可以使用表变量的方式来解决这个问题,SQL语句如下:

    declare @t table (分数 int)
    insert into @t (分数) (select 分数 from tb where 分数>90)
    select * from tb where 分数 in (select * from @t)

    虽然上面的SQL语句要比第一种方式更复杂,但却将子查询放在了表变量@t中,这样做将使SQL语句更容易维护,但又会带来另一个问题,就是性能的损失。

    由于表变量实际上使用了临时表,从而增加了额外的I/O开销,因此,表变量的方式并不太适合数据量大且频繁查询的情况。

    为此,在SQL Server 中提供了另外一种解决方案,这就是公用表表达式(CTE),使用CTE,可以使SQL语句的可维护性,同时,CTE要比表变量的效率高得多。

    with cr as 
    (
        select 分数 from tb where 分数>90
    )
    select * from tb where 分数 in (select * from cr)

    4、在使用CTE时应注意如下几点:

    4.1. CTE后面必须直接跟使用CTE的SQL语句(如select、insert、update等),否则,CTE将失效。如下面的SQL语句将无法正常使用CTE:

    with cr as 
    (
        select 分数 from tb where 分数>90
    )
    select * from tb --应将这条SQL语句去掉
    select * from tb where 分数 in (select * from cr) --使用CTE的SQL语句应紧跟在相关的CTE后面

    4.2. CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔,如下面的SQL语句所示

    with cr1 as
    (
        select * from tb 
    ),
    cr2 as
    (
        select * from tb 
    ),
    cr3 as
    (
        select * from tb 
    )
    select a.* from cr1 a, cr2 b, cr3 c where a.分数 = b.分数 and a.分数 = c.分数

    4.3. 如果CTE的表达式名称与某个数据表或视图重名,则紧跟在该CTE后面的SQL语句使用的仍然是CTE,当然,后面的SQL语句使用的就是数据表或视图了,如下面的SQL语句所示:

    with tb as
    (
        select Name from Student 
    )
    select * from tb 

    4.4. 如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾,如下面的SQL所示:

    declare @t table (分数 int)
    insert into @t (分数) (select 分数 from tb where 分数>90);--必须加分号
    with tr as
    (
        select 分数 from tb where 分数 in (select * from @t)
    )
    select * from tr
  • 相关阅读:
    剑指offer-整数中1出现的次数
    数据流中的中位数
    二叉搜索树的后序遍历序列
    Java 线程阻塞和唤醒
    Java 线程池
    Python哈希表和解析式
    Python线性数据结构
    python 基础知识
    pyenv虚拟环境管理python多版本和软件库
    Paramiko的SSH和SFTP使用
  • 原文地址:https://www.cnblogs.com/yuan-jun/p/6505800.html
Copyright © 2020-2023  润新知