SQL中使用WITH AS提高性能-使用公用表表达式(CTE)简化嵌套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短语里的数据放入一个全局临时表里。很多查询通过这种方法都可以提高速度。
二.使用方法
先看下面一个嵌套的查询语句:

select * from person.StateProvince where CountryRegionCode in
         (select CountryRegionCode from person.CountryRegion where Name like 'C%')

    上面的查询语句使用了一个子查询。虽然这条SQL语句并不复杂,但如果嵌套的层次过多,会使SQL语句非常难以阅读和维护。因此,也可以使用表变量的方式来解决这个问题,SQL语句如下:

declare @t table(CountryRegionCode nvarchar(3))
insert into @t(CountryRegionCode)  (select CountryRegionCode from person.CountryRegion where Name like 'C%')

select * from person.StateProvince where CountryRegionCode
                     in (select * from @t)


    虽然上面的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
(
    select CountryRegionCode from person.CountryRegion where Name like 'C%'
)

select * from person.StateProvince where CountryRegionCode in (select * from cr)

    其中cr是一个公用表表达式,该表达式在使用上与表变量类似,只是SQL Server 2005在处理公用表表达式的方式上有所不同。

DECLARE @City TABLE(
    ID INT IDENTITY(1,1),
    NAME NVARCHAR(50),
    ParentID INT NULL
)

INSERT INTO @City
VALUES ('上海市', NULL), ('江苏省', NULL), ('浙江省', NULL),
        ('徐汇区', 1), ('闵行区', 1), ('黄浦区', 1),
        ('南京市', 2), ('苏州市', 2), ('常州市', 2),
        ('杭州市', 3), ('温州市', 3), ('余姚市', 3)

--SELECT * FROM @City

;WITH tempCity (Id, NAME, ParentID, CityLevel)
AS
(
    SELECT
        ID, NAME, ParentID, 0 AS CityLevel
    FROM
        @City
    WHERE
        ParentID IS NULL
    UNION ALL
    SELECT
        c.ID, c.NAME, c.ParentID, CityLevel + 1
    FROM
        @City c
    JOIN
        tempCity t
    ON
        c.ParentID = t.Id
)

SELECT * FROM tempCity

 


;WITH entities(entityId, setEntityFieldTaskTypeId, valueToSet)  AS (
    SELECT 
        customerID,
,
        CAST('8' AS VARCHAR(20))
    FROM 
        ADMIN.dbo.customers WITH(NOLOCK)
    WHERE
        customerID = 13255
    UNION ALL
    SELECT
        cia.iproBrokerID,
,
        CAST('0' AS VARCHAR(20))
    FROM
        ADMIN.dbo.customerIproAccounts cia WITH(NOLOCK), entities e
    WHERE
        cia.customerID = e.entityId AND
        e.setEntityFieldTaskTypeId = 4
    UNION ALL
    SELECT
        bm.eProBrokerID,
,
        CAST('False' AS VARCHAR(20))
    FROM
        dbo.brokerMappings bm WITH(NOLOCK), entities e
    WHERE
        BM.iProBrokerID = e.entityId AND
        e.setEntityFieldTaskTypeId = 3
)

--SELECT * FROM entities

SELECT
    st.*
FROM
    dbo.scheduledTask st WITH(NOLOCK)
INNER JOIN
    dbo.setEntityFieldTask seft WITH(NOLOCK)
ON
    st.scheduledTaskId = seft.scheduledTaskId
INNER JOIN
    entities e
ON
    e.entityId = seft.entityId AND
    e.setEntityFieldTaskTypeId = seft.setEntityFieldTaskTypeId AND
    e.valueToSet = seft.valueToSet
WHERE
    st.taskStatusId = 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WITH AS是用来定义一个SQL片断,该SQL片断会被整个SQL语句所用到的语法。这个语句被称为公用表达式CTE),它可以让子查询重用相同的with查询块,并且可以在多个地方被引用。使用WITH AS可以提高查询的效率,避免重复查询相同的数据。WITH AS的语法是在查询语句之前定义,使用select调用,一般在需要多次使用相同查询的情况下使用。WITH关键字只能使用一次,多个查询用逗号分割。WITH子句的返回结果存储在用户的临时空间,可以在后面的查询反复使用,从而提高查询效率。在同级select前有多个查询定义的时候,第一个使用WITH关键字,后面的不需要使用。最后一个WITH子句与下面的查询之间不能有逗号,只能用右括号分割,WITH子句的查询必须用括号括起来。如果定义了WITH子句,而在查询没有使用,会报错ORA-32035,解决方法是移除未被引用的WITH查询。WITH子句定义的查询可以在后面的WITH子句使用,但一个WITH子句内部不能嵌套另一个WITH子句。在引用WITH子句的结果列时,必须使用别名或*。所以,当你使用SQL语句的WITH AS语法时,你可以定义一个查询块并给它起一个别名,然后在后面的查询直接使用这个别名来引用这个查询块的结果。<span class="em">1</span> #### 引用[.reference_title] - *1* [SQL语句 with as 用法](https://blog.csdn.net/weixin_72476421/article/details/130481353)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值