当前位置: 首页 > news >正文

SqlServer公用表表达式 (CTE) WITH common_table_expression

SQL Server 中的公用表表达式(Common Table Expressions,简称 CTE)是一种临时命名的结果集,它在执行查询时存在,并且只在该查询执行期间有效。CTE 类似于一个临时的视图或者一个内嵌的查询,但它提供了更好的可读性和重用性。

CTE 使用 WITH 子句来定义,后面紧跟着一个或多个 CTE 的名称和定义(即 SELECT 语句)。然后,在查询的主体中,你可以像引用表一样引用这些 CTE。

1、本文内容

  • 语法
  • 参数
  • 创建和使用公用表表达式的准则
  • 定义和使用递归公用表表达式的准则
  • 示例

适用于:

  • Microsoft Fabric Microsoft Fabric
  • Warehouse 中的 SQL Server
  • Azure SQL 数据库
  • Azure SQL 托管实例
  • Azure Synapse Analytics
  • Analytics Platform System (PDW)
  • SQL Analytics 终结点

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

参考官方地址:
https://learn.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-ver16

2、语法

[ WITH <common_table_expression> [ ,...n ] ]<common_table_expression>::=expression_name [ ( column_name [ ,...n ] ) ]AS( CTE_query_definition )

3、参数

  • expression_name
    公用表表达式的有效标识符。 expression_name 须不同于在同一 WITH <common_table_expression> 子句中定义的任何其他公用表表达式的名称,但可以与基表或基视图的名称相同。 在查询中对 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。

4、创建和使用公用表表达式的准则

下面的准则适用于非递归公用表表达式。 有关适用于递归公用表表达式的准则,请参阅后面的定义和使用递归公用表表达式的准则。

  • 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 中使用以下子句:

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

    • INTO

    • 带有查询提示的 OPTION 子句

    • FOR BROWSE

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

  • 可以使用引用 CTE 的查询来定义游标。

  • 可以在 CTE 中引用远程服务器中的表。

  • 在执行 CTE 时,任何引用 CTE 的提示都可能与该 CTE 访问其基础表时发现的其他提示相冲突,这种冲突与引用查询中的视图的提示所发生的冲突相同。 发生这种情况时,查询将返回错误。

5、定义和使用递归公用表表达式的准则

下面的准则适用于定义递归公用表表达式:

  • 递归 CTE 定义至少必须包含两个 CTE 查询定义,一个定位点成员和一个递归成员。 可以定义多个定位点成员和递归成员;但必须将所有定位点成员查询定义置于第一个递归成员定义之前。 所有 CTE 查询定义都是定位点成员,但它们引用 CTE 本身时除外。

  • 定位点成员必须与以下集合运算符之一结合使用:UNION ALL、UNION、INTERSECT 或 EXCEPT。 在最后一个定位点成员和第一个递归成员之间,以及组合多个递归成员时,只能使用 UNION ALL 集合运算符。

  • 定位点成员和递归成员中的列数必须一致。

  • 递归成员中列的数据类型必须与定位点成员中相应列的数据类型一致。

  • 递归成员的 FROM 子句只能引用一次 CTE expression_name。

  • 在递归成员的 CTE_query_definition 中不能出现下列项:

    • SELECT DISTINCT

    • GROUP BY

    • PIVOT(当数据库兼容性级别为 110 或更高级别时。请参阅 SQL Server 2016 中数据库引擎功能的中断性变更。)

    • HAVING

    • 标量聚合

    • TOP

    • LEFT、RIGHT、OUTER JOIN(允许使用 INNER JOIN)

    • 子查询

    • 应用于 CTE_query_definition 中 CTE 的递归引用的提示。

下面的准则适用于使用递归公用表表达式:

  • 无论参与的 SELECT 语句返回的列的为 Null 性如何,递归 CTE 返回的全部列都可以为空。

  • 如果递归 CTE 组合不正确,可能会导致无限循环。 例如,如果递归成员查询定义对父列和子列返回相同的值,则会造成无限循环。 可以使用 MAXRECURSION 提示以及在 INSERT、UPDATE、DELETE 或 SELECT 语句的 OPTION 子句中的一个 0 到 32,767 之间的值,来限制特定语句所允许的递归级数,以防止出现无限循环。 这样就能够在解决产生循环的代码问题之前控制语句的执行。 服务器范围的默认值为 100。 如果指定 0,则没有限制。 每个语句只能指定一个 MAXRECURSION 值。 有关详细信息,请参阅 查询提示 (Transact-SQL)。

  • 不能使用包含递归公用表表达式的视图来更新数据。

  • 可以使用 CTE 在查询上定义游标。 CTE 是定义游标结果集的 select_statement 参数。 递归 CTE 只允许使用快速只进游标和静态(快照)游标。 如果在递归 CTE 中指定了其他游标类型,则该类型将转换为静态游标类型。

  • 可以在 CTE 中引用远程服务器中的表。 如果在 CTE 的递归成员中引用了远程服务器,那么将为每个远程表创建一个假脱机,这样就可以在本地反复访问这些表。 如果为 CTE 查询,Index Spool/Lazy Spool 则显示在查询计划中,并具有额外的 WITH STACK 谓词。 这是一种确认正确递归的方法。

  • CTE 递归部分中的分析和聚合函数适用于当前递归级别的集合而不适用于 CTE 集合。 ROW_NUMBER 之类的函数仅对当前递归级别传递给它们的数据子集执行运算,而不对传递给 CTE 的递归部分的整个数据集合执行运算。 有关详细信息,请参阅示例 I. 在随后的递归 CTE 中使用分析函数。

6、示例

下载示例数据库AdventureWorks sample databases
https://github.com/microsoft/sql-server-samples/releases/tag/adventureworks

6.1、下例显示每名销售代表每年的销售订单总数。

-- Define the CTE expression name and column list.
WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear)
AS
-- Define the CTE query.
(SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYearFROM Sales.SalesOrderHeaderWHERE SalesPersonID IS NOT NULL
)
-- Define the outer query referencing the CTE name.
SELECT SalesPersonID, COUNT(SalesOrderID) AS TotalSales, SalesYear
FROM Sales_CTE
GROUP BY SalesYear, SalesPersonID
ORDER BY SalesPersonID, SalesYear;

以下为返回部分结果集

SalesPersonID TotalSales  SalesYear
------------- ----------- -----------
274           4           2011
274           22          2012
274           14          2013
274           8           2014
275           65          2011
275           148         2012
275           175         2013
275           62          2014
276           46          2011
276           151         2012
276           162         2013
276           59          2014
277           59          2011
277           166         2012
277           185         2013
277           63          2014
278           30          2011
278           80          2012
278           89          2013
278           35          2014

6.2、使用公用表表达式来限制次数和报告平均数

以下示例显示销售代表在所有年度内的平均销售订单数。

WITH Sales_CTE (SalesPersonID, NumberOfOrders)
AS
(   SELECT SalesPersonID, COUNT(*)FROM Sales.SalesOrderHeaderWHERE SalesPersonID IS NOT NULLGROUP BY SalesPersonID
)
SELECT AVG(NumberOfOrders) AS "Average Sales Per Person"
FROM Sales_CTE;-- 返回结果
Average Sales Per Person
------------------------
223(1 行受影响)

6.3、在单个查询中使用多个 CTE 定义

下面的示例显示如何在单个查询中定义多个 CTE。 注意,其中使用逗号分隔 CTE 查询定义。 SQL Server 2012 和更高版本中提供 FORMAT 函数,用于以货币格式显示货币金额。

WITH Sales_CTE (SalesPersonID, TotalSales, SalesYear)
AS
-- Define the first CTE query.
(SELECT SalesPersonID, SUM(TotalDue) AS TotalSales, YEAR(OrderDate) AS SalesYearFROM Sales.SalesOrderHeaderWHERE SalesPersonID IS NOT NULLGROUP BY SalesPersonID, YEAR(OrderDate))
, -- Use a comma to separate multiple CTE definitions.-- Define the second CTE query, which returns sales quota data by year for each sales person.
Sales_Quota_CTE (BusinessEntityID, SalesQuota, SalesQuotaYear)
AS
(SELECT BusinessEntityID, SUM(SalesQuota)AS SalesQuota, YEAR(QuotaDate) AS SalesQuotaYearFROM Sales.SalesPersonQuotaHistoryGROUP BY BusinessEntityID, YEAR(QuotaDate)
)-- Define the outer query by referencing columns from both CTEs.
SELECT SalesPersonID, SalesYear, FORMAT(TotalSales,'C','en-us') AS TotalSales, SalesQuotaYear, FORMAT (SalesQuota,'C','en-us') AS SalesQuota, FORMAT (TotalSales -SalesQuota, 'C','en-us') AS Amt_Above_or_Below_Quota
FROM Sales_CTE
JOIN Sales_Quota_CTE ON Sales_Quota_CTE.BusinessEntityID = Sales_CTE.SalesPersonIDAND Sales_CTE.SalesYear = Sales_Quota_CTE.SalesQuotaYear
ORDER BY SalesPersonID, SalesYear;

以下为部分结果集

SalesPersonID SalesYear   TotalSales              SalesQuotaYear SalesQuota         Amt_Above_or_Below_Quota	
------------- ----------- ----------------------- -------------- -----------------------------------------------
274           2011        $32,567.92              2011           $126,000.00        ($93,432.08)
274           2012        $516,197.37             2012           $471,000.00        $45,197.37
274           2013        $485,880.64             2013           $521,000.00        ($35,119.36)
274           2014        $201,288.52             2014           $187,000.00        $14,288.52
275           2011        $986,298.09             2011           $1,425,000.00      ($438,701.91)
275           2012        $3,806,298.31           2012           $4,032,000.00      ($225,701.69)
275           2013        $4,490,942.20           2013           $4,836,000.00      ($345,057.80)
275           2014        $1,191,828.47           2014           $869,000.00        $322,828.47
276           2011        $1,294,819.74           2011           $2,083,000.00      ($788,180.26)
276           2012        $4,328,860.05           2012           $3,863,000.00      $465,860.05
276           2013        $4,637,217.83           2013           $4,716,000.00      ($78,782.17)
276           2014        $1,434,121.43           2014           $1,124,000.00      $310,121.43
277           2011        $1,477,158.28           2011           $2,283,000.00      ($805,841.72)
277           2012        $4,865,650.84           2012           $4,743,000.00      $122,650.84
277           2013        $3,827,980.36           2013           $4,225,000.00      ($397,019.64)
277           2014        $1,171,596.41           2014           $947,000.00        $224,596.41
278           2011        $563,326.55             2011           $866,000.00        ($302,673.45)
278           2012        $1,448,035.53           2012           $1,451,000.00      ($2,964.47)
278           2013        $1,567,161.73           2013           $1,658,000.00      ($90,838.27)
278           2014        $490,898.41             2014           $390,000.00        $100,898.41

6.4、使用递归公用表表达式显示递归的多个级别

以下示例显示经理以及向经理报告的雇员的层次列表。 该示例首先创建并填充 dbo.MyEmployees 表。

-- Create an Employee table.
CREATE TABLE dbo.T_Employees
(
EmployeeID SMALLINT NOT NULL,
FirstName NVARCHAR(30) NOT NULL,
LastName NVARCHAR(40) NOT NULL,
Title NVARCHAR(50) NOT NULL,
DeptID SMALLINT NOT NULL,
ManagerID SMALLINT NULL,
CONSTRAINT PK_T_EmployeeID PRIMARY KEY CLUSTERED (EmployeeID ASC)
);
-- Populate the table with values.
INSERT INTO dbo.T_Employees VALUES
(1, N'Ken', N'Sánchez', N'Chief Executive Officer',16, NULL)
,(273, N'Brian', N'Welcker', N'Vice President of Sales', 3, 1)
,(274, N'Stephen', N'Jiang', N'North American Sales Manager', 3, 273)
,(275, N'Michael', N'Blythe', N'Sales Representative', 3, 274)
,(276, N'Linda', N'Mitchell', N'Sales Representative', 3, 274)
,(285, N'Syed', N'Abbas', N'Pacific Sales Manager', 3, 273)
,(286, N'Lynn', N'Tsoflias', N'Sales Representative', 3, 285)
,(16, N'David', N'Bradley', N'Marketing Manager', 4, 273)
,(23, N'Mary', N'Gibson', N'Marketing Specialist', 4, 16);
WITH DirectReports(ManagerID, EmployeeID, Title, EmployeeLevel) AS
(SELECT ManagerID, EmployeeID, Title, 0 AS EmployeeLevelFROM dbo.T_EmployeesWHERE ManagerID IS NULLUNION ALLSELECT e.ManagerID, e.EmployeeID, e.Title, EmployeeLevel + 1FROM dbo.T_Employees AS eINNER JOIN DirectReports AS d ON e.ManagerID = d.EmployeeID
)
SELECT ManagerID, EmployeeID, Title, EmployeeLevel
FROM DirectReports
ORDER BY ManagerID;

返回结果集

ManagerID EmployeeID Title                                              EmployeeLevel
--------- ---------- -------------------------------------------------- -------------
NULL      1          Chief Executive Officer                            0
1         273        Vice President of Sales                            1
16        23         Marketing Specialist                               3
273       16         Marketing Manager                                  2
273       274        North American Sales Manager                       2
273       285        Pacific Sales Manager                              2
274       275        Sales Representative                               3
274       276        Sales Representative                               3
285       286        Sales Representative                               3(9 行受影响)

6.5、使用递归公用表表达式显示递归的两个级别

以下示例显示经理以及向经理报告的雇员。 将返回的级别数目限制为两个。

WITH DirectReports(ManagerID, EmployeeID, Title, EmployeeLevel) AS
(SELECT ManagerID, EmployeeID, Title, 0 AS EmployeeLevelFROM dbo.T_EmployeesWHERE ManagerID IS NULLUNION ALLSELECT e.ManagerID, e.EmployeeID, e.Title, EmployeeLevel + 1FROM dbo.T_Employees AS eINNER JOIN DirectReports AS d ON e.ManagerID = d.EmployeeID
)
SELECT ManagerID, EmployeeID, Title, EmployeeLevel
FROM DirectReports
WHERE EmployeeLevel <= 2 ;

返回结果集

ManagerID EmployeeID Title                                              EmployeeLevel
--------- ---------- -------------------------------------------------- -------------
NULL      1          Chief Executive Officer                            0
1         273        Vice President of Sales                            1
273       16         Marketing Manager                                  2
273       274        North American Sales Manager                       2
273       285        Pacific Sales Manager                              2(5 行受影响)

6.6、使用递归公用表表达式显示层次列表

以下示例添加了经理和员工的姓名,以及他们各自的头衔。 通过缩进各个级别,突出显示经理和雇员的层次结构。

WITH DirectReports(Name, Title, EmployeeID, EmployeeLevel, Sort)
AS (SELECT CONVERT(VARCHAR(255), e.FirstName + ' ' + e.LastName),e.Title,e.EmployeeID,1,CONVERT(VARCHAR(255), e.FirstName + ' ' + e.LastName)FROM dbo.T_Employees AS eWHERE e.ManagerID IS NULLUNION ALLSELECT CONVERT(VARCHAR(255), REPLICATE ('|    ' , EmployeeLevel) +e.FirstName + ' ' + e.LastName),e.Title,e.EmployeeID,EmployeeLevel + 1,CONVERT (VARCHAR(255), RTRIM(Sort) + '|    ' + FirstName + ' ' + LastName)FROM dbo.T_Employees AS eJOIN DirectReports AS d ON e.ManagerID = d.EmployeeID)
SELECT EmployeeID, Name, Title, EmployeeLevel
FROM DirectReports
ORDER BY Sort;

返回结果集

EmployeeID Name                                      Title                                              EmployeeLevel
---------- ----------------------------------------  -------------------------------------------------- -------------
1          Ken Sánchez                               Chief Executive Officer                            1
273        |    Brian Welcker                        Vice President of Sales                            2
16         |    |    David Bradley                   Marketing Manager                                  3
23         |    |    |    Mary Gibson                Marketing Specialist                               4
274        |    |    Stephen Jiang                   North American Sales Manager                       3
276        |    |    |    Linda Mitchell             Sales Representative                               4
275        |    |    |    Michael Blythe             Sales Representative                               4
285        |    |    Syed Abbas                      Pacific Sales Manager                              3
286        |    |    |    Lynn Tsoflias              Sales Representative                               4(9 行受影响)

在这个递归 CTE 的例子中,我们首先选择所有的顶级经理(锚点成员),然后递归地选择每个经理的直接下属,同时跟踪他们在层级结构中的位置(通过 Level 列)。

6.7、使用 MAXRECURSION 取消一条语句

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

--Creates an infinite loop
WITH cte (EmployeeID, ManagerID, Title) AS
(SELECT EmployeeID, ManagerID, TitleFROM dbo.T_EmployeesWHERE ManagerID IS NOT NULLUNION ALLSELECT cte.EmployeeID, cte.ManagerID, cte.TitleFROM cteJOIN dbo.T_Employees 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);

返回结果集,并由错误提示

EmployeeID ManagerID Title
---------- --------- --------------------------------------------------
16         273       Marketing Manager
23         16        Marketing Specialist
273        1         Vice President of Sales
274        273       North American Sales Manager
275        274       Sales Representative
276        274       Sales Representative
285        273       Pacific Sales Manager
286        285       Sales Representative
286        285       Sales Representative
286        285       Sales Representative
消息 530,级别 16,状态 1,第 1333 行
The statement terminated. The maximum recursion 2 has been exhausted before statement completion.

在更正代码错误之后,就不再需要 MAXRECURSION。 以下示例显示了更正后的代码。

WITH cte (EmployeeID, ManagerID, Title)
AS
(SELECT EmployeeID, ManagerID, TitleFROM dbo.T_EmployeesWHERE ManagerID IS NOT NULLUNION ALLSELECT e.EmployeeID, e.ManagerID, e.TitleFROM dbo.T_Employees AS e INNER JOIN cte ON e.ManagerID = cte.EmployeeID
)
SELECT EmployeeID, ManagerID, Title
FROM cte;
EmployeeID ManagerID Title
---------- --------- --------------------------------------------------
16         273       Marketing Manager
23         16        Marketing Specialist
273        1         Vice President of Sales
274        273       North American Sales Manager
275        274       Sales Representative
276        274       Sales Representative
285        273       Pacific Sales Manager
286        285       Sales Representative
286        285       Sales Representative
275        274       Sales Representative
276        274       Sales Representative
16         273       Marketing Manager
274        273       North American Sales Manager
285        273       Pacific Sales Manager
286        285       Sales Representative
275        274       Sales Representative
276        274       Sales Representative
23         16        Marketing Specialist
23         16        Marketing Specialist(19 行受影响)

6.8、使用公用表表达式来有选择地执行 SELECT 语句中的递归关系操作

以下示例显示了为 ProductAssemblyID = 800 生产自行车所需的产品装配和部件层次结构。

USE AdventureWorks2022;
GO
WITH Parts(AssemblyID, ComponentID, PerAssemblyQty, EndDate, ComponentLevel) AS
(SELECT b.ProductAssemblyID, b.ComponentID, b.PerAssemblyQty,b.EndDate, 0 AS ComponentLevelFROM Production.BillOfMaterials AS bWHERE b.ProductAssemblyID = 800AND b.EndDate IS NULLUNION ALLSELECT bom.ProductAssemblyID, bom.ComponentID, p.PerAssemblyQty,bom.EndDate, ComponentLevel + 1FROM Production.BillOfMaterials AS bomINNER JOIN Parts AS p ON bom.ProductAssemblyID = p.ComponentIDAND bom.EndDate IS NULL
)
SELECT AssemblyID, ComponentID, Name, PerAssemblyQty, EndDate,ComponentLevel
FROM Parts AS pINNER JOIN Production.Product AS pr ON p.ComponentID = pr.ProductID
ORDER BY ComponentLevel, AssemblyID, ComponentID;

返回结果集

AssemblyID  ComponentID Name                                               PerAssemblyQty                          EndDate                 ComponentLevel
----------- ----------- -------------------------------------------------- --------------------------------------- ----------------------- --------------
800         518         ML Road Seat Assembly                              1.00                                    NULL                    0
800         806         ML Headset                                         1.00                                    NULL                    0
800         812         ML Road Handlebars                                 1.00                                    NULL                    0
800         819         ML Road Front Wheel                                1.00                                    NULL                    0
800         827         ML Road Rear Wheel                                 1.00                                    NULL                    0
800         835         ML Road Frame-W - Yellow, 44                       1.00                                    NULL                    0
800         894         Rear Derailleur                                    1.00                                    NULL                    0
800         907         Rear Brakes                                        1.00                                    NULL                    0
800         939         ML Road Pedal                                      1.00                                    NULL                    0
800         945         Front Derailleur                                   1.00                                    NULL                    0
800         948         Front Brakes                                       1.00                                    NULL                    0
800         950         ML Crankset                                        1.00                                    NULL                    0
800         952         Chain                                              1.00                                    NULL                    0
800         994         LL Bottom Bracket                                  1.00                                    NULL                    0
518         497         Pinch Bolt                                         1.00                                    NULL                    1
518         528         Seat Lug                                           1.00                                    NULL                    1
518         530         Seat Post                                          1.00                                    NULL                    1
518         912         ML Road Seat/Saddle                                1.00                                    NULL                    1
806         1           Adjustable Race                                    1.00                                    NULL                    1
806         4           Headset Ball Bearings                              1.00                                    NULL                    1
806         323         Crown Race                                         1.00                                    NULL                    1
806         402         Keyed Washer                                       1.00                                    NULL                    1
806         459         Lock Nut 19                                        1.00                                    NULL                    1
806         462         Lower Head Race                                    1.00                                    NULL                    1
812         329         Road End Caps                                      1.00                                    NULL                    1
812         357         ML Grip Tape                                       1.00                                    NULL                    1
812         398         Handlebar Tube                                     1.00                                    NULL                    1
812         529         Stem                                               1.00                                    NULL                    1
819         401         HL Hub                                             1.00                                    NULL                    1
819         490         LL Nipple                                          1.00                                    NULL                    1
819         506         Reflector                                          1.00                                    NULL                    1
819         511         ML Road Rim                                        1.00                                    NULL                    1
819         527         Spokes                                             1.00                                    NULL                    1
819         922         Road Tire Tube                                     1.00                                    NULL                    1
819         932         ML Road Tire                                       1.00                                    NULL                    1
827         401         HL Hub                                             1.00                                    NULL                    1
827         490         LL Nipple                                          1.00                                    NULL                    1
827         506         Reflector                                          1.00                                    NULL                    1
827         511         ML Road Rim                                        1.00                                    NULL                    1
827         527         Spokes                                             1.00                                    NULL                    1
827         922         Road Tire Tube                                     1.00                                    NULL                    1
827         932         ML Road Tire                                       1.00                                    NULL                    1
835         324         Chain Stays                                        1.00                                    NULL                    1
835         325         Decal 1                                            1.00                                    NULL                    1
835         326         Decal 2                                            1.00                                    NULL                    1
835         327         Down Tube                                          1.00                                    NULL                    1
835         399         Head Tube                                          1.00                                    NULL                    1
835         496         Paint - Yellow                                     1.00                                    NULL                    1
835         532         Seat Stays                                         1.00                                    NULL                    1
835         533         Seat Tube                                          1.00                                    NULL                    1
835         534         Top Tube                                           1.00                                    NULL                    1
835         803         ML Fork                                            1.00                                    NULL                    1
894         355         Guide Pulley                                       1.00                                    NULL                    1
894         535         Tension Pulley                                     1.00                                    NULL                    1
894         679         Rear Derailleur Cage                               1.00                                    NULL                    1
945         351         Front Derailleur Cage                              1.00                                    NULL                    1
945         352         Front Derailleur Linkage                           1.00                                    NULL                    1
950         318         ML Crankarm                                        1.00                                    NULL                    1
950         320         Chainring Bolts                                    1.00                                    NULL                    1
950         321         Chainring Nut                                      1.00                                    NULL                    1
950         322         Chainring                                          1.00                                    NULL                    1
950         332         Freewheel                                          1.00                                    NULL                    1
994         3           BB Ball Bearing                                    1.00                                    NULL                    1
994         525         LL Shell                                           1.00                                    NULL                    1
3           2           Bearing Ball                                       1.00                                    NULL                    2
3           461         Lock Ring                                          1.00                                    NULL                    2
3           504         Cup-Shaped Race                                    1.00                                    NULL                    2
3           505         Cone-Shaped Race                                   1.00                                    NULL                    2
324         486         Metal Sheet 5                                      1.00                                    NULL                    2
327         483         Metal Sheet 3                                      1.00                                    NULL                    2
329         482         Metal Sheet 2                                      1.00                                    NULL                    2
398         487         Metal Sheet 6                                      1.00                                    NULL                    2
399         485         Metal Sheet 4                                      1.00                                    NULL                    2
401         524         HL Spindle/Axle                                    1.00                                    NULL                    2
401         524         HL Spindle/Axle                                    1.00                                    NULL                    2
401         526         HL Shell                                           1.00                                    NULL                    2
401         526         HL Shell                                           1.00                                    NULL                    2
529         477         Metal Bar 1                                        1.00                                    NULL                    2
532         484         Metal Sheet 7                                      1.00                                    NULL                    2
533         478         Metal Bar 2                                        1.00                                    NULL                    2
534         482         Metal Sheet 2                                      1.00                                    NULL                    2
803         316         Blade                                              1.00                                    NULL                    2
803         331         Fork End                                           1.00                                    NULL                    2
803         350         Fork Crown                                         1.00                                    NULL                    2
803         531         Steerer                                            1.00                                    NULL                    2
316         486         Metal Sheet 5                                      1.00                                    NULL                    3
331         482         Metal Sheet 2                                      1.00                                    NULL                    3
350         486         Metal Sheet 5                                      1.00                                    NULL                    3
531         487         Metal Sheet 6                                      1.00                                    NULL                    3(89 行受影响)

6.9、在 UPDATE 语句中使用递归 CTE

下例更新用于生成产品‘Road-550-W Yellow, 44’ (ProductAssemblyID``800 的所有部件的 PerAssemblyQty 值。 公用表表达式将返回用于生成 ProductAssemblyID 800 的部件和用于生成这些部件的组件等的层次结构列表。 只修改公用表表达式所返回的行。

USE AdventureWorks2022;
GO
WITH Parts(AssemblyID, ComponentID, PerAssemblyQty, EndDate, ComponentLevel) AS
(SELECT b.ProductAssemblyID, b.ComponentID, b.PerAssemblyQty,b.EndDate, 0 AS ComponentLevelFROM Production.BillOfMaterials AS bWHERE b.ProductAssemblyID = 800AND b.EndDate IS NULLUNION ALLSELECT bom.ProductAssemblyID, bom.ComponentID, p.PerAssemblyQty,bom.EndDate, ComponentLevel + 1FROM Production.BillOfMaterials AS bomINNER JOIN Parts AS p ON bom.ProductAssemblyID = p.ComponentIDAND bom.EndDate IS NULL
)
UPDATE Production.BillOfMaterials
SET PerAssemblyQty = c.PerAssemblyQty * 2
FROM Production.BillOfMaterials AS cINNER JOIN Parts AS d ON c.ProductAssemblyID = d.AssemblyID
WHERE d.ComponentLevel = 0;

6.10、使用多个定位点和递归成员

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

-- Genealogy table
IF OBJECT_ID('dbo.T_Person','U') IS NOT NULL DROP TABLE dbo.T_Person;
GO
CREATE TABLE dbo.T_Person(ID int, Name VARCHAR(30), Mother INT, Father INT);
GO
INSERT dbo.T_Person
VALUES (1, 'Sue', NULL, NULL),(2, 'Ed', NULL, NULL),(3, 'Emma', 1, 2),(4, 'Jack', 1, 2),(5, 'Jane', NULL, NULL),(6, 'Bonnie', 5, 4),(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 MotherFROM dbo.T_PersonWHERE Name = 'Bonnie'
UNION
-- Second anchor member returns Bonnie's father.SELECT FatherFROM dbo.T_PersonWHERE Name = 'Bonnie'
UNION ALL
-- First recursive member returns male ancestors of the previous generation.SELECT T1.FatherFROM Generation AS T2 INNER JOIN  dbo.T_Person AS T1 ON T2.ID=T1.ID
UNION ALL
-- Second recursive member returns female ancestors of the previous generation.SELECT T1.MotherFROM Generation AS T2 INNER JOIN  dbo.T_Person AS T1 ON T2.ID=T1.ID
)
SELECT  T1.ID,T1.Name,T1.Mother, T1.Father
FROM Generation AS T2 INNER JOIN  dbo.T_Person AS T1 ON T2.ID = T1.ID;
GO

返回结果集

ID          Name                           Mother      Father
----------- ------------------------------ ----------- -----------
4           Jack                           1           2
5           Jane                           NULL        NULL
2           Ed                             NULL        NULL
1           Sue                            NULL        NULL(4 行受影响)

相关文章:

SqlServer公用表表达式 (CTE) WITH common_table_expression

SQL Server 中的公用表表达式&#xff08;Common Table Expressions&#xff0c;简称 CTE&#xff09;是一种临时命名的结果集&#xff0c;它在执行查询时存在&#xff0c;并且只在该查询执行期间有效。CTE 类似于一个临时的视图或者一个内嵌的查询&#xff0c;但它提供了更好的…...

常见中间件漏洞

Tomcat CVE-2017-12615 1.打开环境&#xff0c;抓包 2.切换请求头为 PUT&#xff0c;请求体添加木马&#xff0c;并在请求头添加木马文件名 1.jsp&#xff0c;后方需要以 / 分隔 3.连接 后台弱口令部署war包 1.打开环境,进入指点位置,账户密码均为 tomcat 2.在此处上传一句话…...

elasticsearch的学习(二):Java api操作elasticsearch

简介 使用Java api操作elasticsearch 创建maven项目 pom.xml文件 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…...

docker 部署 ElasticSearch;Kibana

ELasticSearch 创建网络 docker network create es-netES配合Kibana使用时需要组网&#xff0c;使两者运行在同一个网络下 命令 docker run -d \ --name es \ -e "discovery.typesingle-node" \ -v /usr/local/es/data:/usr/share/elasticsearch/data \ -v /usr/…...

k8s使用kustomize来部署应用

k8s使用kustomize来部署应用 本文主要是讲述kustomzie的基本用法。首先&#xff0c;我们说一下部署文件的目录结构。 ./ ├── base │ ├── deployment.yaml │ ├── kustomization.yaml │ └── service.yaml └── overlays└── dev├── kustomization.…...

基于开源FFmpeg和SDL2.0的音视频解码播放和存储系统的实现

目录 1、FFMPEG简介 2、SDL简介 3、视频播放器原理 4、FFMPEG多媒体编解码库 4.1、FFMPEG库 4.2、数据类型 4.3、解码 4.3.1、接口函数 4.3.2、解码流程 4.4、存储&#xff08;推送&#xff09; 4.4.1、接口函数 4.4.2、存储流程 5、SDL库介绍 5.1、数据结构 5.…...

保姆级教程,一文了解LVS

目录 一.什么是LVS tips: 二.优点&#xff08;为什么要用LVS&#xff1f;&#xff09; 三.作用 四.程序组成 五.LVS 负载均衡集群的类型 六.分布式内容 六.一.分布式存储 六.二.分布式计算 六.三.分布式常见应用 tips&#xff1a; 七.LVS 涉及相关的术语 八.LVS 负…...

【STM32】DMA数据转运(存储器到存储器)

本篇博客重点在于标准库函数的理解与使用&#xff0c;搭建一个框架便于快速开发 目录 DMA简介 DMA时钟使能 DMA初始化 转运起始和终止的地址 转运方向 数据宽度 传输次数 转运触发方式 转运模式 通道优先级 开启DMA通道 DMA初始化框架 更改转运次数 DMA应用实例-…...

【Android】通过代码打开输入法

获取焦点 binding.editText.requestFocus()打开键盘 val imm getSystemService(InputMethodManager::class.java) imm.showSoftInput(binding.editText, InputMethodManager.SHOW_IMPLICIT)...

爬虫集群部署:Scrapyd 框架深度解析

&#x1f575;️‍♂️ 爬虫集群部署&#xff1a;Scrapyd 框架深度解析 &#x1f6e0;️ Scrapyd 环境部署 Scrapyd 是一个开源的 Python 爬虫框架&#xff0c;专为分布式爬虫设计。它允许用户在集群中调度和管理爬虫任务&#xff0c;并提供了简洁的 API 进行控制。以下是 Scr…...

pytorch GPU操作事例

>>> import torch >>> if_cuda torch.cuda.is_available() >>> print("if_cuda",if_cuda) if_cuda True >>> gpu_count torch.cuda.device_count() >>> print("gpu_count",gpu_count) gpu_count 8...

linux常见性能监控工具

常用命令top、free 、vmsata、iostat 、sar命令 具体更详细命令可以查看手册&#xff0c;这里只是简述方便找工具 整体性能top,内存看free&#xff0c;磁盘cpu内存历史数据可以vmsata、iostat 、sar、iotop top命令 交互&#xff1a;按P按照CPU排序&#xff0c;按M按照内存…...

C++ | Leetcode C++题解之第331题验证二叉树的前序序列化

题目&#xff1a; 题解&#xff1a; class Solution { public:bool isValidSerialization(string preorder) {int n preorder.length();int i 0;int slots 1;while (i < n) {if (slots 0) {return false;}if (preorder[i] ,) {i;} else if (preorder[i] #){slots--;i…...

【多模态处理】利用GPT逐一读取本地图片并生成描述并保存,支持崩溃后从最新进度恢复

【多模态处理】利用GPT逐一读取本地图片并生成描述&#xff0c;支持崩溃后从最新进度恢复题 代码功能&#xff1a;核心功能最后碎碎念 代码&#xff08;使用中转平台url&#xff09;&#xff1a;代码&#xff08;直接使用openai的key&#xff09; 注意 代码功能&#xff1a; 读…...

【rk3588】获取相机画面

需求&#xff1a;获取相机画面&#xff0c;并在连接HDMI线&#xff0c;在显示器上显示 查找设备 v4l2-ctl --list-devices H65 USB CAMERA: H65 USB CAMERA (usb-0000:00:14.0-1):/dev/video2/dev/video3播放视频 gst-launch-1.0 v4l2src device/dev/video22 ! video/x-ra…...

数据结构的基本概念

数据结构的基本概念 数据是什么&#xff1f; 数据 &#xff1a; 数据是信息的载体&#xff0c;是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序识别&#xff08;二进制0|1&#xff09;和处理的符号的集合。数据是计算机程序加工的原料。 早期计算机处理的…...

AI人工智能机器学习

AI人工智能 机器学习的类型(ML) 学习意味着通过学习或经验获得知识或技能。 基于此&#xff0c;我们可以定义机器学习(ML) 它被定义为计算机科学领域&#xff0c;更具体地说是人工智能的应用&#xff0c;它提供计算机系统学习数据和改进经验而不被明确编程的能力。 基本上&…...

试用AWS全新神器:Amazon Bedrock的「Open Artifacts」版Claude.ai Artifacts

Claude.ai的Artifacts真是太方便了。 GitHub上的AWS Samples仓库中有一个仿制Artifacts的应用程序。 Open Artifacts for Amazon Bedrock https://github.com/aws-samples/open_artifacts_for_bedrockhttps://github.com/aws-samples/open_artifacts_for_bedrock本文将介绍「…...

W3C XML 活动

关于W3C的XML活动&#xff0c;XML&#xff08;可扩展标记语言&#xff09;是一种用于描述、存储、传送及交换数据的标准。W3C&#xff08;万维网联盟&#xff09;对XML的发展起到了关键作用&#xff0c;推出了一系列的版本和相关的技术规范。 XML版本历史&#xff1a; XML 1.0&…...

vue请求springboot接口下载zip文件

说明 其实只需要按照普通文件流下载即可&#xff0c;以下是一个例子&#xff0c;仅供参考。 springboot接口 RestController RequestMapping("/api/files") public class FileController {GetMapping("/download")public ResponseEntity<Resource>…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...

sshd代码修改banner

sshd服务连接之后会收到字符串&#xff1a; SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢&#xff1f; 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头&#xff0c…...