sql性能优化:SQLServerwithas的作用提高重复sql语句执行效率;这个语法递。。。

更新时间:2023-07-04 14:27:19 阅读: 评论:0

sql性能优化:SQLServerwithas的作⽤提⾼重复sql语句执⾏
效率;这个语法递。。。
注意:虽然本⽂是转载,但是内容⾥⾯,作者加了⼀些便于阅读的“注释”,“数据表”等
⼀.WITH AS的含义
WITH AS短语,也叫做⼦查询部分(subquery factoring),可以让你做很多事情,定义⼀个SQL⽚断,该SQL⽚断会被整个SQL语句所⽤到。有的时候,是为了让SQL语句的可读性更⾼些,也有可能是在UNION ALL的不同部分,作为提供数据的部分。
特别对于UNION ALL⽐较有⽤。因为UNION ALL的每个部分可能相同,但是如果每个部分都去执⾏⼀遍的话,则成本太⾼,所以可以使⽤WITH AS短语,则只要执⾏⼀遍即可。如果WITH AS短语所定义的表名被调⽤两次以上,则优化器会⾃动将WITH AS短语所获取的数据放⼊⼀个TEMP表⾥,如果只是被调⽤⼀次,则不会。⽽提⽰materialize则是强制将WITH AS短语⾥的数据放⼊⼀个全局临时表⾥。很多查询通过这种⽅法都可以提⾼速度。
--------------------
/*番外篇 UNION*/
--------------------
UNION 操作符⽤于合并两个或多个 SELECT 语句的结果集。
请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。
【SQL UNION 语法】
SELECT column_name(s) FROM table_name1
当家是什么意思
UNION
SELECT column_name(s) FROM table_name2
注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使⽤ UNION ALL。
【SQL UNION ALL 语法】
SELECT column_name(s) FROM table_name1
中医考研科目UNION ALL
SELECT column_name(s) FROM table_name2
另外,UNION 结果集中的列名总是等于 UNION 中第⼀个 SELECT 语句中的列名。
下⾯的例⼦中使⽤的原始表:
[表Employees_China:]
E_ID E_Name
01    Zhang, Hua
02    Wang, Wei
03    Carter, Thomas
04    Yang, Ming
[表Employees_USA]
E_ID E_Name
01    Adams, John
02    Bush, George
03    Carter, Thomas
04    Gates, Bill
【使⽤ UNION 命令】
实例
实例
列出所有在中国和美国的不同的雇员名:
SELECT E_Name FROM Employees_China
UNION
SELECT E_Name FROM Employees_USA
结果
E_Name
Zhang, Hua
Wang, Wei
Carter, Thomas
Yang, Ming
Adams, John
Bush, George
Gates, Bill
注释:这个命令⽆法列出在中国和美国的所有雇员。在上⾯的例⼦中,我们有两个名字相同的雇员,他们当中只有⼀个⼈被列出来了。UNION 命令只会选取不同的值。
UNION ALL
UNION ALL 命令和 UNION 命令⼏乎是等效的,不过 UNION ALL 命令会列出所有的值。
【使⽤ UNION ALL 命令】
实例:
列出在中国和美国的所有的雇员:
SELECT E_Name FROM Employees_China
UNION ALL
SELECT E_Name FROM Employees_USA
结果
俄剧E_Name
Zhang, Hua
Wang, Wei
Carter, Thomas
Yang, Ming
Adams, John
Bush, George
Carter, Thomas
Gates, Bill
摘录:/sql/sql_union.asp
⼆.使⽤⽅法
表:person.StateProvince(⼈国家省)
字段名类型说明
CountryRegionCode ---国家地区代码给女朋友唱的歌
-
--------
---------
表:person.CountryRegion(国家地区)
字段名类型说明
Name---名称
---------
---------
先看下⾯⼀个嵌套的查询语句:
lect * from person.StateProvince where CountryRegionCode in
(lect CountryRegionCode from person.CountryRegion where Name like 'C%')
上⾯的查询语句使⽤了⼀个⼦查询。虽然这条SQL语句并不复杂,但如果嵌套的层次过多,会使SQL语句⾮常难以阅读和维护。因此,也可以使⽤表变量的⽅式来解决这个问题,SQL语句如下:
declare @t table(CountryRegionCode nvarchar(3))
inrt into @t(CountryRegionCode) (lect CountryRegionCode from person.CountryRegion where Name like 'C%')
lect * from person.StateProvince where CountryRegionCode in (lect * from @t)
/*
代码解读
declare @t table(CountryRegionCode nvarchar(3))
声明⼀个变量“t”,类型是:table。
表字段是:CountryRegionCode ,类型是:nvarchar(3)
*/
虽然上⾯的SQL语句要⽐第⼀种⽅式更复杂,但却将⼦查询放在了表变量@t中,这样做将使SQL语句更容易维护,但⼜会带来另⼀个问题,就是性能的损失。由于表变量实际上使⽤了临时表,从⽽增加
了额外的I/O开销,因此,表变量的⽅式并不太适合数据量⼤且频繁查询的情况。为此,在SQL Server 2005中提供了另外⼀种解决⽅案,这就是公⽤表表达式(CTE),使⽤CTE,可以使SQL语句的可维护性,同时,CTE要⽐表变量的效率⾼得多。
下⾯是CTE的语法:
[ WITH <common_table_expression> [ ,n ] ]
<common_table_expression>::=
expression_name [ ( column_name [ ,n ] ) ]
AS
( CTE_query_definition )
现在使⽤CTE来解决上⾯的问题,SQL语句如下:
with
cr as
(
lect CountryRegionCode from person.CountryRegion where Name like 'C%'
)
lect * from person.StateProvince where CountryRegionCode in (lect * from cr)
其中cr是⼀个公⽤表表达式,该表达式在使⽤上与表变量类似,只是SQL Server 2005在处理公⽤表表达式的⽅式上有所不同。
在使⽤CTE时应注意如下⼏点:
1. CTE后⾯必须直接跟使⽤CTE的SQL语句(如lect、inrt、update等),否则,CTE将失效。如下⾯的SQL语句将⽆法正常使⽤CTE:
with
全球最小的国家
cr as
(
lect CountryRegionCode from person.CountryRegion where Name like 'C%'
)
lect * from person.CountryRegion -- 应将这条SQL语句去掉
-- 使⽤CTE的SQL语句应紧跟在相关的CTE后⾯ --
lect * from person.StateProvince where CountryRegionCode in (lect * from cr)
新员工培训目的2. CTE后⾯也可以跟其他的CTE,但只能使⽤⼀个with,多个CTE中间⽤逗号(,)分隔,如下⾯的SQL语句所⽰:寻觅中华
with
cte1 as
(
lect * from table1 where name like 'abc%'
),
cte2 as
(
lect * from table2 where id > 20
),
cte3 as
(
lect * from table3 where price < 100
)
lect 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
(
lect * from persons where age < 30
)
lect * from table1 -- 使⽤了名为table1的公共表表达式
lect * 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)
t @s = 'C%'
; -- 必须加分号
with
t_tree as
(
lect CountryRegionCode from person.CountryRegion where Name like @s
)
lect * from person.StateProvince where CountryRegionCode in (lect * from t_tree)
CTE除了可以简化嵌套SQL语句外,还可以进⾏递归调⽤
三、递归调⽤
先看如下⼀个数据表(t_tree):
表:t_tree(国家地区)
字段名类型说明
id int id
node_name nvarchar名称
parent_id int⽗id
上图显⽰了⼀个表中的数据,这个表有三个字段:id、node_name、parent_id。实际上,这个表中保存了⼀个树型结构,分三层:省、市、区。其中id表⽰当前省、市或区的id号、node_name表⽰名称、parent_id表⽰节点的⽗节点的id。
现在有⼀个需求,要查询出某个省下⾯的所有市和区(查询结果包含省)。如果只使⽤SQL语句来实现,需要使⽤到游标、临时表等技术。但在SQL Server2005中还可以使⽤CTE来实现。
从这个需求来看属于递归调⽤,也就是说先查出满⾜调价的省的记录,在本例⼦中的要查“辽宁省”的记录,如下:
id  node_name  parent_id
1    辽宁省        0
三明医改然后再查所有parent_id字段值为1的记录,如下:
id  node_name  parent_id
2      沈阳市      1
3      ⼤连市      1
最后再查parent_id字段值为2或3的记录,如下:
id    node_name    parent_id
4      ⼤东区        2
5      沈河区        2
6      铁西区        2
将上⾯三个结果集合并起来就是最终结果集。

本文发布于:2023-07-04 14:27:19,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1067543.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:语句   查询   部分   结果   变量   定义   数据   问题
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图