SQL With (递归CTE查询)

指定临时命名的结果集,这些结果集称为公用表表达式 (CTE)。该表达式源自简单查询,并且在单条 SELECT、INSERT、UPDATE 或 DELETE 语句的执行范围内定义。该子句也可用在 CREATE VIEW 语句中,作为该语句的 SELECT 定义语句的一部分。公用表表达式可以包括对自身的引用。这种表达式称为递归公用表表达式。

语法

[ WITH <common_table_expression> [ ,...n ] ]

<common_table_expression>::=
        expression_name [ ( column_name [ ,...n ] ) ]
    AS
        ( CTE_query_definition )
-------------------------------------------------------------------------------------------------------------
参数
expression_name
公用表表达式的有效标识符。 expression_name 必须与在同一 WITH <common_table_expression> 子句中定义的任何其他公用表表达式的名称不同,但 expression_name 可以与基表或基视图的名称相同。在查询中对 expression_name 的任何引用都会使用公用表表达式,而不使用基对象。

column_name
在公用表表达式中指定列名。在一个 CTE 定义中不允许出现重复的名称。指定的列名数必须与 CTE_query_definition 结果集中列数匹配。只有在查询定义中为所有结果列都提供了不同的名称时,列名称列表才是可选的。

CTE_query_definition
指定一个其结果集填充公用表表达式的 SELECT 语句。除了 CTE 不能定义另一个 CTE 以外,CTE_query_definition 的 SELECT 语句必须满足与创建视图时相同的要求。有关详细信息,请参阅“备注”部分和 CREATE VIEW (Transact-SQL)。

如果定义了多个 CTE_query_definition,则这些查询定义必须用下列一个集合运算符联接起来:UNION ALL、UNION、EXCEPT 或 INTERSECT。有关如何使用递归 CTE 查询定义的详细信息,请参阅下面的“备注”部分和使用公用表表达式的递归查询。
-----------------------------------------------------------------------------------------------------------------
备注 创建和使用 CTE 的指南 下列指南应用于非递归 CTE。有关适用于递归 CTE 的指南,请参阅后面的“定义和使用递归 CTE 的指南”。 CTE 之后必须跟随引用部分或全部 CTE 列的单条 SELECT、INSERT、UPDATE 或 DELETE 语句。也可以在 CREATE VIEW 语句中将 CTE 指定为视图中 SELECT 定义语句的一部分。 可以在非递归 CTE 中定义多个 CTE 查询定义。定义必须与以下集合运算符之一结合使用:UNION ALL、UNION、INTERSECT 或 EXCEPT。
CTE 可以引用自身,也可以引用在同一 WITH 子句中预先定义的 CTE。不允许前向引用。
不允许在一个 CTE 中指定多个 WITH 子句。例如,如果 CTE_query_definition 包含一个子查询,则该子查询不能包括定义另一个 CTE 的嵌套的 WITH 子句。
不能在 CTE_query_definition 中使用以下子句:
   COMPUTE 或 COMPUTE BY
   ORDER BY(除非指定了 TOP 子句)
   INTO
   带有查询提示的 OPTION 子句
   FOR XML
   FOR BROWSE
如果将 CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾。
可以使用引用 CTE 的查询来定义游标。
可以在 CTE 中引用远程服务器中的表。
在执行 CTE 时,任何引用 CTE 的提示都可能与该 CTE 访问其基础表时发现的其他提示相冲突,这种冲突与引用查询中的视图的提示所发生的冲突相同。发生这种情况时,查询将返回错误。有关详细信息,请参阅视图解析。
定义和使用递归 CTE 指南
下列指南适用于定义递归 CTE 的情况:

递归 CTE 定义至少必须包含两个 CTE 查询定义,一个定位点成员和一个递归成员。可以定义多个定位点成员和递归成员;但必须将所有定位点成员查询定义置于第一个递归成员定义之前。所有 CTE 查询定义都是定位点成员,但它们引用 CTE 本身时除外。
定位点成员必须与以下集合运算符之一结合使用:UNION ALL、UNION、INTERSECT 或 EXCEPT。在最后一个定位点成员和第一个递归成员之间,以及组合多个递归成员时,只能使用 UNION ALL 集合运算符。
定位点成员和递归成员中的列数必须一致。
递归成员中列的数据类型必须与定位点成员中相应列的数据类型一致。
递归成员的 FROM 子句只能引用一次 CTE expression_name。
在递归成员的 CTE_query_definition 中不允许出现下列项:
   SELECT DISTINCT
   GROUP BY
   HAVING
   标量聚合
   TOP
   LEFT、RIGHT、OUTER JOIN(允许出现 INNER JOIN)
   子查询
   应用于对 CTE_query_definition 中的 CTE 的递归引用的提示。
下列指南适用于使用递归 CTE:

无论参与的 SELECT 语句返回的列的为空性如何,递归 CTE 返回的全部列都可以为空。
如果递归 CTE 组合不正确,可能会导致无限循环。例如,如果递归成员查询定义对父列和子列返回相同的值,则会造成无限循环。可以使用 MAXRECURSION 提示以及在 INSERT、UPDATE、DELETE 或 SELECT 语句的 OPTION 子句中的一个 0 到 32,767 之间的值,来限制特定语句所允许的递归级数,以防止出现无限循环。这样就能够在解决产生循环的代码问题之前控制语句的执行。服务器范围内的默认值是 100。如果指定 0,则没有限制。每一个语句只能指定一个 MAXRECURSION 值。有关详细信息,请参阅查询提示 (Transact-SQL)。
不能使用包含递归公用表表达式的视图来更新数据。
可以使用 CTE 在查询上定义游标。CTE 是定义游标结果集的 select_statement 参数。递归 CTE 只允许使用快速只进游标和静态(快照)游标。如果在递归 CTE 中指定了其他游标类型,则该类型将转换为静态游标类型。
可以在 CTE 中引用远程服务器中的表。如果在 CTE 的递归成员中引用了远程服务器,那么将为每个远程表创建一个假脱机,这样就可以在本地反复访问这些表。
-----------------------------------------------------------------------------------------------------------------示例
A. 创建一个简单公用表表达式
以下示例显示直接向 Adventure Works Cycles 的每个经理报告的雇员的数目。

USE AdventureWorks;
GO
WITH DirReps(ManagerID, DirectReports) AS
(
    SELECT ManagerID, COUNT(*)
    FROM HumanResources.Employee AS e
    WHERE ManagerID IS NOT NULL
    GROUP BY ManagerID
)
SELECT ManagerID, DirectReports
FROM DirReps
ORDER BY ManagerID;
GO

B. 使用公用表表达式来限制次数和报告平均数
以下示例显示向经理报告的雇员的平均数。

WITH DirReps (Manager, DirectReports) AS
(
    SELECT ManagerID, COUNT(*) AS DirectReports
    FROM HumanResources.Employee
    GROUP BY ManagerID
)
SELECT AVG(DirectReports) AS [Average Number of Direct Reports]
FROM DirReps
WHERE DirectReports>= 2 ;
GO

C. 多次引用同一个公用表表达式
以下示例显示 SalesOrderHeader 表中每个销售人员的销售订单的总数和最近的销售订单的日期。CTE 在运行的语句中被引用两次:一次返回为销售人员所选的列,另一次检索销售经理的类似详细信息。销售人员和销售经理的数据都返回在一行中。

USE AdventureWorks;
GO
WITH Sales_CTE (SalesPersonID, NumberOfOrders, MaxDate)
AS
(
    SELECT SalesPersonID, COUNT(*), MAX(OrderDate)
    FROM Sales.SalesOrderHeader
    GROUP BY SalesPersonID
)
SELECT E.EmployeeID, OS.NumberOfOrders, OS.MaxDate,
    E.ManagerID, OM.NumberOfOrders, OM.MaxDate
FROM HumanResources.Employee AS E
    JOIN Sales_CTE AS OS
    ON E.EmployeeID = OS.SalesPersonID
    LEFT OUTER JOIN Sales_CTE AS OM
    ON E.ManagerID = OM.SalesPersonID
ORDER BY E.EmployeeID;
GO

使用递归公用表表达式显示递归的多个级别。
以下示例显示经理以及向经理报告的雇员的层次列表。

USE AdventureWorks;
GO
WITH DirectReports(ManagerID, EmployeeID, EmployeeLevel) AS
(
    SELECT ManagerID, EmployeeID, 0 AS EmployeeLevel
    FROM HumanResources.Employee
    WHERE ManagerID IS NULL
    UNION ALL
    SELECT e.ManagerID, e.EmployeeID, EmployeeLevel + 1
    FROM HumanResources.Employee e
        INNER JOIN DirectReports d
        ON e.ManagerID = d.EmployeeID
)
SELECT ManagerID, EmployeeID, EmployeeLevel
FROM DirectReports ;
GO

E. 使用递归公用表表达式显示递归的两个级别。
以下示例显示经理以及向经理报告的雇员。将返回的级别数目被限制为两个。

USE AdventureWorks;
GO
WITH DirectReports(ManagerID, EmployeeID, EmployeeLevel) AS
(
    SELECT ManagerID, EmployeeID, 0 AS EmployeeLevel
    FROM HumanResources.Employee
    WHERE ManagerID IS NULL
    UNION ALL
    SELECT e.ManagerID, e.EmployeeID, EmployeeLevel + 1
    FROM HumanResources.Employee e
        INNER JOIN DirectReports d
        ON e.ManagerID = d.EmployeeID
)
SELECT ManagerID, EmployeeID, EmployeeLevel
FROM DirectReports
WHERE EmployeeLevel <= 2 ;
GO

F. 使用递归公用表表达式显示层次列表
以下示例在示例 C 的基础上添加经理和雇员的名称,以及他们各自的头衔。通过缩进各个级别,突出显示经理和雇员的层次结构。

USE AdventureWorks;
GO
WITH DirectReports(Name, Title, EmployeeID, EmployeeLevel, Sort)
AS (SELECT CONVERT(varchar(255), c.FirstName + ‘ ‘ + c.LastName),
        e.Title,
        e.EmployeeID,
        1,
        CONVERT(varchar(255), c.FirstName + ‘ ‘ + c.LastName)
    FROM HumanResources.Employee AS e
    JOIN Person.Contact AS c ON e.ContactID = c.ContactID
    WHERE e.ManagerID IS NULL
    UNION ALL
    SELECT CONVERT(varchar(255), REPLICATE (‘| ‘ , EmployeeLevel) +
        c.FirstName + ‘ ‘ + c.LastName),
        e.Title,
        e.EmployeeID,
        EmployeeLevel + 1,
        CONVERT (varchar(255), RTRIM(Sort) + ‘| ‘ + FirstName + ‘ ‘ +
                 LastName)
    FROM HumanResources.Employee as e
    JOIN Person.Contact AS c ON e.ContactID = c.ContactID
    JOIN DirectReports AS d ON e.ManagerID = d.EmployeeID
    )
SELECT EmployeeID, Name, Title, EmployeeLevel
FROM DirectReports
ORDER BY Sort;
GO

G. 使用 MAXRECURSION 取消一条语句
可以使用 MAXRECURSION 来防止不合理的递归 CTE 进入无限循环。以下示例特意创建了一个无限循环,然后使用 MAXRECURSION 提示将递归级别限制为两级。

USE AdventureWorks;
GO
--Creates an infinite loop
WITH cte (EmployeeID, ManagerID, Title) as
(
    SELECT EmployeeID, ManagerID, Title
    FROM HumanResources.Employee
    WHERE ManagerID IS NOT NULL
  UNION ALL
    SELECT cte.EmployeeID, cte.ManagerID, cte.Title
    FROM cte
    JOIN  HumanResources.Employee AS e
        ON cte.ManagerID = e.EmployeeID
)
--Uses MAXRECURSION to limit the recursive levels to 2
SELECT EmployeeID, ManagerID, Title
FROM cte
OPTION (MAXRECURSION 2);
GO
在更正代码错误之后,就不再需要 MAXRECURSION。以下示例显示了更正后的代码。

USE AdventureWorks;
GO
WITH cte (EmployeeID, ManagerID, Title)
AS
(
    SELECT EmployeeID, ManagerID, Title
    FROM HumanResources.Employee
    WHERE ManagerID IS NOT NULL
  UNION ALL
    SELECT  e.EmployeeID, e.ManagerID, e.Title
    FROM HumanResources.Employee AS e
    JOIN cte ON e.ManagerID = cte.EmployeeID
)
SELECT EmployeeID, ManagerID, Title
FROM cte;
GO

H. 使用公用表表达式来有选择地执行 SELECT 语句中的递归操作
以下示例显示了为 ProductAssemblyID = 800 生产自行车所需的产品装配和部件层次结构。

USE AdventureWorks;
GO
WITH Parts(AssemblyID, ComponentID, PerAssemblyQty, EndDate, ComponentLevel) AS
(
    SELECT b.ProductAssemblyID, b.ComponentID, b.PerAssemblyQty,
        b.EndDate, 0 AS ComponentLevel
    FROM Production.BillOfMaterials AS b
    WHERE b.ProductAssemblyID = 800
          AND b.EndDate IS NULL
    UNION ALL
    SELECT bom.ProductAssemblyID, bom.ComponentID, p.PerAssemblyQty,
        bom.EndDate, ComponentLevel + 1
    FROM Production.BillOfMaterials AS bom
        INNER JOIN Parts AS p
        ON bom.ProductAssemblyID = p.ComponentID
        AND bom.EndDate IS NULL
)
SELECT AssemblyID, ComponentID, Name, PerAssemblyQty, EndDate,
        ComponentLevel
FROM Parts AS p
    INNER JOIN Production.Product AS pr
    ON p.ComponentID = pr.ProductID
ORDER BY ComponentLevel, AssemblyID, ComponentID;
GO

I. 在 UPDATE 语句中使用递归 CTE
以下示例将直接或间接向 ManagerID 12 报告的所有雇员的 VacationHours 值增加 25%。公用表表达式将返回直接向 ManagerID 12 报告的雇员以及直接向这些雇员报告的雇员等的层次列表。只修改公用表表达式所返回的行。

USE AdventureWorks;
GO
WITH DirectReports(EmployeeID, NewVacationHours, EmployeeLevel)
AS
(SELECT e.EmployeeID, e.VacationHours, 1
  FROM HumanResources.Employee AS e
  WHERE e.ManagerID = 12
  UNION ALL
  SELECT e.EmployeeID, e.VacationHours, EmployeeLevel + 1
  FROM HumanResources.Employee as e
  JOIN DirectReports AS d ON e.ManagerID = d.EmployeeID
)
UPDATE HumanResources.Employee
SET VacationHours = VacationHours * 1.25
FROM HumanResources.Employee AS e
JOIN DirectReports AS d ON e.EmployeeID = d.EmployeeID;
GO

使用多个定位点和递归成员
以下示例使用多个定位点和递归成员来返回指定的人的所有祖先。创建了一个表,并在表中插入值,以建立由递归 CTE 返回的宗谱。

-- Genealogy table
IF OBJECT_ID(‘Person‘,‘U‘) IS NOT NULL DROP TABLE Person;
GO
CREATE TABLE Person(ID int, Name varchar(30), Mother int, Father int);
GO
INSERT Person VALUES(1, ‘Sue‘, NULL, NULL);
INSERT Person VALUES(2, ‘Ed‘, NULL, NULL);
INSERT Person VALUES(3, ‘Emma‘, 1, 2);
INSERT Person VALUES(4, ‘Jack‘, 1, 2);
INSERT Person VALUES(5, ‘Jane‘, NULL, NULL);
INSERT Person VALUES(6, ‘Bonnie‘, 5, 4);
INSERT Person VALUES(7, ‘Bill‘, 5, 4);
GO
-- Create the recursive CTE to find all of Bonnie‘s ancestors.
WITH Generation (ID) AS
(
-- First anchor member returns Bonnie‘s mother.
    SELECT Mother
    FROM Person
    WHERE Name = ‘Bonnie‘
UNION
-- Second anchor member returns Bonnie‘s father.
    SELECT Father
    FROM Person
    WHERE Name = ‘Bonnie‘
UNION ALL
-- First recursive member returns male ancestors of the previous generation.
    SELECT Person.Father
    FROM Generation, Person
    WHERE Generation.ID=Person.ID
UNION ALL
-- Second recursive member returns female ancestors of the previous generation.
    SELECT Person.Mother
    FROM Generation, Person
    WHERE Generation.ID=Person.ID
)
SELECT Person.ID, Person.Name, Person.Mother, Person.Father
FROM Generation, Person
WHERE Generation.ID = Person.ID;
GO
 详情参见http://msdn.microsoft.com/zh-cn/library/ms175972(v=SQL.90).aspx
一个数据表(t_tree):表中的数据有三个字段: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
  将上面三个结果集合并起来就是最终结果集。
  上述的查询过程也可以按递归的过程进行理解,即先查指定的省的记录(辽宁省),得到这条记录后,就有了相应的id值,然后就进入了的递归过程,如下图所示。

从上面可以看出,递归的过程就是使用union all合并查询结果集的过程,也就是相当于下面的递归公式:
  resultset(n) = resultset(n-1)union allcurrent_resultset
  其中resultset(n)表示最终的结果集,resultset(n - 1)表示倒数第二个结果集,current_resultset表示当前查出来的结果集,而最开始查询出“辽宁省”的记录集相当于递归的初始条件。而递归的结束条件是current_resultset为空。下面是这个递归过程的伪代码:
  publicresultsetgetResultSet(resultset)
  {
  if(resultsetisnull)
  {
  current_resultset=第一个结果集(包含省的记录集)
  将结果集的id保存在集合中
  getResultSet(current_resultset)
  }
  current_resultset=根据id集合中的id值查出当前结果集
  if(current_resultisnull)returnresultset
  将当前结果集的id保存在集合中
  return getResultSet(resultsetunionallcurrent_resultset)
  }
  //获得最终结果集
  resultset=getResultSet(null)
  从上面的过程可以看出,这一递归过程实现起来比较复杂,然而CTE为我们提供了简单的语法来简化这一过程。
  实现递归的CTE语法如下:
  [WITH[,n]]
  ::=
  expression_name[(column_name[,n])]
  AS(
  CTE_query_definition1 -- 定位点成员(也就是初始值或第一个结果集)
  unionall
  CTE_query_definition2 -- 递归成员
  )
  下面是使用递归CTE来获得“辽宁省”及下面所有市、区的信息的SQL语句:
  with
  districtas
  (
  -- 获得第一个结果集,并更新最终结果集
  select*fromt_treewherenode_name=N’辽宁省’
  unionall
  -- 下面的select语句首先会根据从上一个查询结果集中获得的id值来查询parent_id
  -- 字段的值,然后district就会变当前的查询结果集,并继续执行下面的select语句
  -- 如果结果集不为null,则与最终的查询结果合并,同时用合并的结果更新最终的查
  -- 询结果;否则停止执行。最后district的结果集就是最终结果集。
  selecta.*fromt_treea,districtb
  wherea.parent_id=b.id
  )
  select*fromdistrict
  查询后的结果如下图所示。

下面的CTE查询了非叶子节点:
  with
  districtas
  (
  select*fromt_treewherenode_name=N’辽宁省’
  unionall
  selecta.*fromt_treea,districtb
  wherea.parent_id=b.id
  ),
  district1as
  (
  selecta.*fromdistrictawherea.idin(selectparent_idfromdistrict)  )
  select*fromdistrict1
  查询结果如下图所示。

注:只有“辽宁省”和“沈阳市”有下子节点。
  在定义和使用递归CTE时应注意如下几点:
  1.递归 CTE 定义至少必须包含两个 CTE 查询定义,一个定位点成员和一个递归成员。可以定义多个定位点成员和递归成员;但必须将所有定位点成员查询定义置于第一个递归成员定义之前。所有 CTE 查询定义都是定位点成员,但它们引用 CTE 本身时除外。
  2.定位点成员必须与以下集合运算符之一结合使用:UNION ALL、UNION、INTERSECT 或 EXCEPT。在最后一个定位点成员和第一个递归成员之间,以及组合多个递归成员时,只能使用 UNION ALL 集合运算符。
  3.定位点成员和递归成员中的列数必须一致。
  4.递归成员中列的数据类型必须与定位点成员中相应列的数据类型一致。
  5.递归成员的 FROM 子句只能引用一次 CTE expression_name。
  6.在递归成员的 CTE_query_definition 中不允许出现下列项:
  (1)SELECT DISTINCT
  (2)GROUP BY
  (3)HAVING
  (4)标量聚合
  (5)TOP
  (6)LEFT、RIGHT、OUTER JOIN(允许出现 INNER JOIN)
  (7)子查询
  (8)应用于对 CTE_query_definition 中的 CTE 的递归引用的提示。
  7.无论参与的 SELECT 语句返回的列的为空性如何,递归 CTE 返回的全部列都可以为空。
  8.如果递归 CTE 组合不正确,可能会导致无限循环。例如,如果递归成员查询定义对父列和子列返回相同的值,则会造成无限循环。可以使用 MAXRECURSION 提示以及在 INSERT、UPDATE、DELETE 或 SELECT 语句的 OPTION 子句中的一个 0 到 32,767 之间的值,来限制特定语句所允许的递归级数,以防止出现无限循环。这样就能够在解决产生循环的代码问题之前控制语句的执行。服务器范围内的默认值是 100。如果指定 0,则没有限制。每一个语句只能指定一个 MAXRECURSION 值。
  9.不能使用包含递归公用表表达式的视图来更新数据。
  10.可以使用 CTE 在查询上定义游标。递归 CTE 只允许使用快速只进游标和静态(快照)游标。如果在递归 CTE 中指定了其他游标类型,则该类型将转换为静态游标类型。
  11.可以在 CTE 中引用远程服务器中的表。如果在 CTE 的递归成员中引用了远程服务器,那么将为每个远程表创建一个假脱机,这样就可以在本地反复访问这些表。

原文地址:https://www.cnblogs.com/tianyuanmuge/p/9925599.html

时间: 2024-07-29 07:32:52

SQL With (递归CTE查询)的相关文章

SQL With(递归 CTE 查询)

本文来自:http://www.cnblogs.com/smailxiaobai/archive/2012/01/16/2323291.html 指定临时命名的结果集,这些结果集称为公用表表达式 (CTE).该表达式源自简单查询,并且在单条 SELECT.INSERT.UPDATE 或 DELETE 语句的执行范围内定义.该子句也可用在 CREATE VIEW 语句中,作为该语句的 SELECT 定义语句的一部分.公用表表达式可以包括对自身的引用.这种表达式称为递归公用表表达式.  Transa

【转】SQL:详解递归CTE,非递归CTE用法

公用表表达式(CTE)的定义 公用表达式的定义非常简单,只包含三部分: 公用表表达式的名字(在WITH之后) 所涉及的列名(可选) 一个SELECT语句(紧跟AS之后) 在MSDN中的原型: WITH expression_name [ ( column_name [,...n] ) ] AS ( CTE_query_definition ) 按照是否递归,可以将公用表(CTE)表达式分为递归公用表表达式和非递归公用表表达式. 非递归公用表表达式(CTE) 非递归公用表表达式(CTE)是查询结果

SQL Server2005使用CTE实现递归

本文来自:http://www.cnblogs.com/wenjl520/archive/2010/01/18/1650393.html CTE递归原理: 递归CTE是由两个最小查询构建的.第一个是定位成员(Anchor Member,AM),它是一个非递归查询,第二个是递归成员(Recursive Member,RM),它是递归查询.在CTE括号中(AS 子句之后),定义独立查询或引用回相同CTE的查询,AM与RM由UNION ALL语句分隔.AM紧被调用一次,RM将被重复调用,直到查询不在返

SQL处理多级分类,查询结果呈树形结构

对于多级分类常规的处理方法,很多程序员可能是用程序先读取一级分类记录,然后通过一级分类循环读取下面的子分类 这样处理的弊端是:如果数据量大,子分类很多,达到4级以上,这方法处理极端占用数据库连接池 对性能影响很大. 如果用SQL下面的CTE递归处理的话,一次性就能把结果给查询出来,而且性能很不错 比用程序处理(数据量很大的情况),临时表性能更好,更方便 with area as(select *,id px,cast(id as nvarchar(4000)) px2 from region w

SQL中的CTE通用表表达式

开发人员正在研发的许多项目都涉及编写由基本的 SELECT/FROM/WHERE 类型的语句派生而来的复杂 SQL 语句.其中一种情形是需要编写在 FROM 子句内使用派生表(也称为内联视图)的 Transact-SQL (T-SQL) 查询.这一常规使开发人员能获取一个行集,并立即将该行集加入到 SELECT 语句中的其他表.视图和用户定义函数中.另一种方案是使用视图而不是派生表.这两种方案都有其各自的优势和劣势. 当使用 SQL Server™ 2005 时,我更倾向于第三种方案,就是使用通

Sql Server 存储过程中查询数据无法使用 Union(All)

原文:Sql Server 存储过程中查询数据无法使用 Union(All) 微软Sql Server数据库中,书写存储过程时,关于查询数据,无法使用Union(All)关联多个查询. 1.先看一段正常的SQL语句,使用了Union(All)查询: SELECT ci.CustId --客户编号 , ci.CustNam --客户名称 , ci.ContactBy --联系人 , ci.Conacts --联系电话 , ci.Addr -- 联系地址 , ci.Notes --备注信息 , ai

SQL实现递归及存储过程中In()参数传递解决方案[转]

SQL实现递归及存储过程中In()参数传递解决方案 1.SQL递归 在SQL Server中,我们可以利用表表达式来实现递归算法,一般用于阻止机构的加载及相关性处理. -->实现: 假设OrganiseUnit(组织机构表)中主要的三个字段为OrganiseUnitID(组织机构主键ID).ParentOrganiseUnitID(组织机构父ID).OrganiseName(组织机构名称) ? 1 2 3 4 5 6 7 [sql] with organise as (select * from

SqlServer里,一条sql进行递归删除

Server 2005中提供了公用表表达式(CTE),使用CTE,可以使SQL语句的可维护性,同时,CTE要比表变量的效率高得多. 存储过程方法: 1 create proc up_delete_nclass 2 @did int  3 as 4 with my1 as(select * from News_Class where id = @did 5  union all select News_Class.* from my1, News_Class where my1.id = News

SQL递归查询(with cte as)

http://www.cnblogs.com/xqhppt/archive/2011/02/15/1955366.html 2011-02-15 16:41 by 忧忧夏天, 2415 阅读, 0 评论, 收藏, 编辑 with cte as(select Id,Pid,DeptName,0as lvl from Departmentwhere Id =2unionallselect d.Id,d.Pid,d.DeptName,lvl+1from cte c innerjoin Departme