SQL技巧(二) - CTE(公用表达式)初步接触

简介: CTE - Common Table Expression(公用表达式)是SQL 2005最重要的改进之一。 子查询有时候使用起来嵌套很复杂, 而使用#tmp类似的临时表, 性能又比较差。 这个时候,介于两者之间的解决方案,CTE诞生了。

CTE - Common Table Expression(公用表达式)是SQL 2005最重要的改进之一。

子查询有时候使用起来嵌套很复杂, 而使用#tmp类似的临时表, 性能又比较差。

这个时候,介于两者之间的解决方案,CTE诞生了。

我们可以用它来替代临时表

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

1. CTE后面必须直接跟使用CTE的SQL语句(如select、insert、update等),否则,CTE将失效

2. CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔

如下面的SQL语句所示:

 

with
cte1 as
(
    select * from table1 where name like 'abc%'
),
cte2 as
(
    select * from table2 where id > 20
),
cte3 as
(
    select * from table3 where price < 100
)
select a.* from cte1 a, cte2 b, cte3 c where a.id = b.id and a.id = c.id

 

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

 

如下面的SQL语句所示:


--  table1是一个实际存在的表

with
table1 as
(
    select * from persons where age < 30
)
select * from table1  --  使用了名为table1的公共表表达式
select * from table1  --  使用了名为table1的数据表

4. CTE 可以引用自身,也可以引用在同一 WITH 子句中预先定义的 CTE。不允许前向引用

5. 不能在 CTE_query_definition 中使用以下子句

 

(1)COMPUTE 或 COMPUTE BY

(2)ORDER BY(除非指定了 TOP 子句)

(3)INTO

(4)带有查询提示的 OPTION 子句

(5)FOR XML

(6)FOR BROWSE

 

6. 如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾

如下面的SQL所示:

 

declare @s nvarchar(3)
set @s = 'C%'
;  -- 必须加分号
with
t_tree as
(
    select CountryRegionCode from person.CountryRegion where Name like @s
)
select * from person.StateProvince where CountryRegionCode in (select * from t_tree)

    CTE除了可以简化嵌套SQL语句外,还可以进行递归调用

 

闲话不多说, 来看看我亲自创建的一个查询的例子, 以AdventureWorks数据库为例

 

with BlueProducts(ProductID, Name, ProductNumber, Color)
as
(
     select ProductID, Name, ProductNumber, Color
     from Production.Product
     where Color = ' Blue '
),
PriceOrderDetail(UnitPriceSum, ProductID)
as
(
     select  SUM(UnitPrice), ProductID
     from Sales.SalesOrderDetail
     group  by ProductID
     having  SUM(UnitPrice) > 100000
)

select sod.ProductID, sod.SalesOrderID, BlueProducts.Name  as ProductName, 
        BlueProducts.ProductNumber, BlueProducts.Color, sod.UnitPrice, po.UnitPriceSum
from Sales.SalesOrderDetail  as sod  inner  join BlueProducts
     on sod.ProductID =BlueProducts.ProductID  inner  join PriceOrderDetail po
     on sod.ProductID =po.ProductID
order  by po.UnitPriceSum

 

892 51084 HL Touring Frame - Blue, 54 FR-T98U-54 Blue 602.346 101726.2003
892 51106 HL Touring Frame - Blue, 54 FR-T98U-54 Blue 602.346 101726.2003

......

959 71918 Touring-3000 Blue, 58 BK-T18U-58 Blue 445.41 118367.7075
959 71894 Touring-3000 Blue, 58 BK-T18U-58 Blue 445.41 118367.7075

......

966 51126 Touring-1000 Blue, 46 BK-T79U-46 Blue 1382.7606 800403.8211
966 51131 Touring-1000 Blue, 46 BK-T79U-46 Blue 1311.2385 800403.8211

 

 

目录
相关文章
|
5月前
|
SQL 存储 缓存
揭秘SQL中的公用表表达式:数据查询的新宠儿
揭秘SQL中的公用表表达式:数据查询的新宠儿
63 2
|
6月前
|
消息中间件 SQL RocketMQ
RocketMQ-初体验RocketMQ(10)-过滤消息_SQL92表达式筛选消息
RocketMQ-初体验RocketMQ(10)-过滤消息_SQL92表达式筛选消息
147 0
|
6月前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL表达式:数据的魔法公式
【4月更文挑战第19天】探索Oracle PL/SQL表达式,体验数据的魔法公式。表达式结合常量、变量、运算符和函数,用于数据运算与转换。算术运算符处理数值计算,比较运算符执行数据比较,内置函数如TO_CHAR、ROUND和SUBSTR提供多样化操作。条件表达式如CASE和NULLIF实现灵活逻辑判断。广泛应用于SQL查询和PL/SQL程序,助你驾驭数据,揭示其背后的规律与秘密,成为数据魔法师。
|
6月前
|
SQL Java 关系型数据库
MyBatis的动态SQL之OGNL(Object-Graph Navigation Language)表达式以及各种标签的用法
MyBatis的动态SQL之OGNL(Object-Graph Navigation Language)表达式以及各种标签的用法
109 0
|
6月前
|
SQL
leetcode-SQL-1440. 计算布尔表达式的值
leetcode-SQL-1440. 计算布尔表达式的值
62 1
|
6月前
|
SQL 数据挖掘 数据处理
「SQL面试题库」 No_109 计算布尔表达式的值
「SQL面试题库」 No_109 计算布尔表达式的值
|
6月前
|
SQL Oracle 关系型数据库
Oracle PL/SQL 第三章--运算符与表达式
Oracle PL/SQL 第三章--运算符与表达式
|
2月前
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
4月前
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
115 13
|
4月前
|
SQL
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。