• SQL Server2005数据库查询中使用CTE【原】


    通用表表达式(CTEs)是SQL Server 2005的一项新功能。它们类似于alias(如在SELECT T1.* FROM MyTable T1中),不过功能更为强大。本质上,CTE是一个临时结果集,它仅仅存在于它发生的语句中。您可以在SELECT、INSERT、DELETE、UPDATE或CTEATE VIEW语句中建立一个CTE。CTE类似于派生表,但拥有几项优点。
    CTE的优点

        与派生表不同,CTE能够引用自己本身。如果您不必存储视图,您可以用一个CTE来代替它。在一个语句中,您还可以多次引用CTE。应用CTE,您可以通过一个派生栏对结果进行分组。

        之前,我曾写过有关原子和分子查询的文章。原子查询建立一个表,而分子查询建立在原子查询之上,提供清晰与重复利用。应用CTE也可以达到同样的目的。您可以将查询区域分割成可读的“块”,然后用这些块建立一个复杂的查询。执行递归查询是CTE最重要也是最强大的功能。

        建立CTE

        CTE通过关键字WITH建立,其模板为:
    WITH CTE_name[ (column_name [,...n] ) ] AS ( CTE_query_specification )

        如果在CTE定义中提到的栏名称是唯一的,那么您可以不必给它们命名。不过,您同样也可以对它们重新命名。

        下面的例子应用到SQL Server 2005中的AdventureWorks样本数据库。这个数据库被高度规格化,因此需要几个连接来集合与雇员有关的信息。视图简化了这一操作,但也收集了所有有关雇员的信息,而您可能仅仅需要其中一部分资料。

        AdventureWorks的雇员数据分布在几个表中;而且,雇员与经理被存储在同一个表中(HumanResources.Employee),而他们的姓名(及其它数据)则存储在Person.Contact表中,这使得这个问题更加复杂。

        首先,我们建立一个恢复雇员姓名的CTE。

    WITH cte_Employee AS ( SELECT e.EmployeeID, c.FirstName, c.MiddleName, c.LastName, e.Title AS JobTitle, c.Phone, e.ManagerID FROM HumanResources.EmployeeAS e INNER JOIN Person.ContactAS c ON c.ContactID = e.ContactID )

        然后,我们可从CTE中选择一栏或几栏,就像它是一个标准的表或视图。

        接着我们再进一步。我们需要雇员和他们经理的姓名,于是我们使用CTE两次,把它自身连接起来。下面是完整的查询代码:

    WITH cte_Employee AS ( SELECT e.EmployeeID, c.FirstName, c.MiddleName, c.LastName, e.Title AS JobTitle, c.Phone, e.ManagerID FROM HumanResources.EmployeeAS e INNER JOIN Person.ContactAS c ON c.ContactID = e.ContactID ) SELECT E.FirstName + ' ' E.LastName Employee, M.FirstName + ' ' M.LastName Manager FROM cte_Employee AS E LEFT OUTER JOIN cte_Employee AS M ON E.ManagerID = M.EmployeeID



        限制:不能在一个语句中建立两个CTE。

        总结

        CTE是SQL Server 2005的一项强大而灵活的功能。它使得SQL Server的可读性更强,更易于管理,降低了查询的复杂程度。如上所述,您可以在一个SQL Server语句中多次应用CTE。

    以上是网上找到的一点教程,但实际用起来还远远不止这些,下面有一个我写的例子,经过反复琢磨终于出炉了

     

    CODE

    /*

    --董广祥 脚本日期: 06/23/2009 18:19:17 */

    CREATE PROCEDURE [dbo].[masterialStat]
        @CName NVARCHAR(50),
        @modelType NVARCHAR(20),
        @StartDate SMALLDATETIME,
        @EndDate SMALLDATETIME
    AS
        WITH    tb0 ( CName, beginningStock, CurrentPeriodInput, CurrentPeriodOutput, termEndStock )
                  AS ( SELECT   vyg.CName,
                                SUM(amout)
                                - ISNULL(( SELECT   SUM(amount)
                                           FROM     vyGinYillOutDetail vyd --减去出库
                                           WHERE    vyd.outPutDateTime < @EndDate
                                                    AND vyg.CName = vyd.CName
                                         ), 0)
                                - ISNULL(( SELECT   SUM(amount)
                                           FROM     vRackScrap vr --减去报废
                                           WHERE    outPutDateTime < @EndDate
                                                    AND vyg.CName = vr.CName
                                         ), 0),
                                0,
                                0,
                                0
                       FROM     vyGinYillDetail vyg
                       WHERE    vyg.CName LIKE '%' + @CName + '%'
                                AND vyg.category LIKE '%' + @modelType + '%'
                                AND vyg.YillDate < @StartDate
                       GROUP BY vyg.CName
     --期初结存
                     ) ,
                tb2 ( CName, beginningStock, CurrentPeriodInput, CurrentPeriodOutput, termEndStock )
                  AS ( SELECT   CName,
                                0,
                                0,
                                0,
                                SUM(amout)
                                - ISNULL(( SELECT   SUM(amount)
                                           FROM     vyGinYillOutDetail vyg
                                           WHERE    vyg.outPutDateTime > @EndDate
                                                    AND vyg.CName = vyd.CName
                                         ), 0) --减去出库
                                - ISNULL(( SELECT   SUM(amount)
                                           FROM     vRackScrap vr
                                           WHERE    vr.outPutDateTime > @EndDate
                                                    AND vr.CName = vyd.CName
                                         ), 0) --减去报废
                       FROM     vyGinYillDetail vyd
                       WHERE    vyd.CName LIKE '%' + @CName + '%'
                                AND category LIKE '%' + @modelType + '%'
                                AND YillDate > @StartDate
                       GROUP BY CName --期末结存
                     ) ,
                tb3 ( CName, beginningStock, CurrentPeriodInput, CurrentPeriodOutput, termEndStock )
                  AS ( SELECT   CName,
                                0,
                                SUM(amout),
                                0,
                                0
                       FROM     vyGinYillDetail
                       WHERE    CName LIKE '%' + @CName + '%'
                                AND category LIKE '%' + @modelType + '%'
                                AND YillDate >= @StartDate
                                AND YillDate <= @EndDate
                       GROUP BY CName --本期入库
                     ) ,
                tb4 ( CName, beginningStock, CurrentPeriodInput, CurrentPeriodOutput, termEndStock )
                  AS ( SELECT   CName,
                                0,
                                0,
                                SUM(amount),
                                0
                       FROM     vyGinYillOutDetail
                       WHERE    CName LIKE '%' + @CName + '%'
                                AND category LIKE '%' + @modelType + '%'
                                AND outPutDateTime >= @StartDate
                                AND outPutDateTime <= @EndDate
                       GROUP BY CName --本期出库
                     ) ,
                tb5 ( CName, beginningStock, CurrentPeriodInput, CurrentPeriodOutput, termEndStock )
                  AS ( SELECT   ISNULL(tb0.CName, tb3.CName),
                                ISNULL(tb0.beginningStock, 0),
                                ISNULL(tb3.CurrentPeriodInput, 0),
                                0,
                                0
                       FROM     tb0
                                FULL JOIN tb3 ON tb0.CName = tb3.CName --填充期初结存,本期入库
                     ) ,
                tb6 ( CName, beginningStock, CurrentPeriodInput, CurrentPeriodOutput, termEndStock )
                  AS ( SELECT   ISNULL(tb5.CName, tb4.CName),
                                ISNULL(tb5.beginningStock, 0),
                                ISNULL(tb5.CurrentPeriodInput, 0),
                                ISNULL(tb4.CurrentPeriodOutput, 0),
                                0
                       FROM     tb5
                                FULL JOIN tb4 ON tb5.CName = tb4.CName
     --填充期初结存,本期入库,本期出库
                     ) ,
                tb7 ( CName, beginningStock, CurrentPeriodInput, CurrentPeriodOutput, termEndStock )
                  AS ( SELECT   ISNULL(tb6.CName, tb2.CName),
                                ISNULL(tb6.beginningStock, 0),
                                ISNULL(tb6.CurrentPeriodInput, 0),
                                ISNULL(tb6.CurrentPeriodOutput, 0),
                                ISNULL(tb2.termEndStock, 0)
                       FROM     tb6
                                FULL JOIN tb2 ON tb6.CName = tb2.CName
     --填充期初结存,本期入库,本期出库,期末结存
                     )
            SELECT  CName,
                    beginningStock,
                    CurrentPeriodInput,
                    CurrentPeriodOutput,
                    termEndStock,
                    ( beginningStock + CurrentPeriodInput - CurrentPeriodOutput
                      + termEndStock ) Stock
            FROM    tb7

    本例出自:http://www.cnblogs.com/myssh/archive/2009/06/24/1509896.html

  • 相关阅读:
    随笔2
    随笔
    关于updateElement接口
    随笔1
    本地访问正常,服务器访问乱码 记录
    Redis (error) NOAUTH Authentication required.解决方法
    tomcat启动很慢 停留在 At least one JAR was scanned for TLDs yet contained no TLDs.
    微信公众号消息回复
    微信公众号 报token验证失败
    idea中web.xml报错 Servlet should have a mapping
  • 原文地址:https://www.cnblogs.com/myssh/p/1509896.html
Copyright © 2020-2023  润新知