SQL Server 2008 中的 CTE:如何递归计算小计

2024-02-22

我有一张表,其中汽车的某些零件按层次结构相关,并且每一行中还有制造这些零件的成本。这是该表的简化:

parentId  Id description qty manufacturingCost costDescripcion
-------- --- ----------- --- ----------------- ---------------
NULL      1  Car          1  100               Assembly the car
NULL      2  Motorcycle   1  100               Assembly the motrocycle
 1       11  Wheel        4   20               Assembly the wheel
11      111  Rim          1   50               Manufacture the rim
11      112  Tire         1   60               Manufacture the tire
 1       12  Door+Window  4   30               Assembly the door and the window
12      121  Door         1   30               Manufacture the door
12      122  Window       2   10               Manufacture the window
 2       11  Wheel        2   15               Assembly the wheel

我需要从“汽车”开始获取整个家谱,并显示每个分支的总数量和总成本。更好的解释是:一辆汽车有 4 个车轮,每个车轮有 1 个轮辋和 1 个轮胎,所以我应该得到 1 个汽车、4 个车轮、4 个轮胎、4 个轮辋。成本有点复杂:组装一辆汽车需要 100 美元,但我必须加上组装 4 个车轮 (4x20) 的成本以及制造 4 个轮辋 (4x50) 和 4 个轮胎的成本(4x60),门窗也是如此。

这是预期的结果:

parentId  Id description qty manufacturingCost   recLevel
-------- --- ----------- --- -----------------   ---------------
NULL       1  Car          1 940 (100+4*130+4*80) 0
 1        11  Wheel        4 130 (20+50+60)       1
 1        12  Door+Window  4 80  (30+30+2*10)     1
12       121  Door         4 30                   2
12       122  Window       8 10                   2
11       111  Rim          4 50                   2
11       112  Tire         4 60                   2

我可以使用递归函数或存储过程轻松实现这一目标,但对于更复杂的结构来说它非常慢,因此我尝试使用通用表表达式来实现这一点。但我没有找到计算成本的方法。我使用从顶层开始向下的递归 CTE,得到数量总和,但我应该在结构中从内到外对成本进行求和,我该怎么做?

这是创建表的代码:

CREATE TABLE #Costs 
(
  parentId int, 
  Id int, 
  description varchar(50),
  qty int, 
  manufacturingCost int,
  costDescripcion varchar(150)
)

INSERT INTO #Costs VALUES (NULL , 1, 'Car', 1, 100, 'Assembly the car')
INSERT INTO #Costs VALUES (NULL , 2, 'Motorcycle', 1, 100, 'Assembly the motrocycle')
INSERT INTO #Costs VALUES (1 , 11, 'Wheel', 4, 20, 'Assembly the wheel')
INSERT INTO #Costs VALUES (11 , 111, 'Rim', 1, 50, 'Manufacture the rim')
INSERT INTO #Costs VALUES (11 , 112, 'Tire', 1, 60, 'Manufacture the tire')
INSERT INTO #Costs VALUES (1 , 12, 'Door+Window', 4, 30, 'Assembly the door and the window')
INSERT INTO #Costs VALUES (12 , 121, 'Door', 1, 30, 'Manufacture the door')
INSERT INTO #Costs VALUES (12 , 122, 'Window', 2, 10, 'Manufacture the window')
INSERT INTO #Costs VALUES (2 , 11, 'Wheel', 2, 15, 'Assembly the wheel')

这是我写的 CTE:

with CTE(parentId, id, description, totalQty, manufacturingCost, recLevel)
as
(
  select c.parentId, c.id, c.description, c.qty, c.manufacturingCost, 0
  from #Costs c
  where c.id = 1

  union all

  select c.parentId, c.id, c.description, c.qty * ct.totalQty, c.manufacturingCost, ct.recLevel + 1
  from #Costs c
  inner join CTE ct on ct.id = c.parentId 
)
select * from CTE

这是我得到的结果,正如您所看到的,这不是预期的结果(未添加成本):

parentId  Id description qty manufacturingCost recLevel
-------- --- ----------- --- ----------------- ---------------
NULL       1  Car          1 100                0
 1        11  Wheel        4 20                 1
 1        12  Door+Window  4 30                 1
12       121  Door         4 30                 2
12       122  Window       8 10                 2
11       111  Rim          4 50                 2
11       112  Tire         4 60                 2

使用 CTE 可以做我想做的事吗?如果是这样,我该怎么办?

非常感谢,

Antuan


你可以尝试这样的事情

DECLARE @Table TABLE(
        parentId INT,
        Id INT,
        description VARCHAR(50),
        qty FLOAT,
        manufacturingCost FLOAT,
        costDescripcion VARCHAR(50)
)

INSERT INTO @Table SELECT NULL,1,'Car',1,100,'Assembly the car' 
INSERT INTO @Table SELECT NULL,2,'Motorcycle',1,100,'Assembly the motrocycle' 
INSERT INTO @Table SELECT 1,11,'Wheel',4,20,'Assembly the wheel' 
INSERT INTO @Table SELECT 11,111,'Rim',1,50,'Manufacture the rim' 
INSERT INTO @Table SELECT 11,112,'Tire',1,60,'Manufacture the tire' 
INSERT INTO @Table SELECT 1,12,'Door+Window',4,30,'Assembly the door and the window' 
INSERT INTO @Table SELECT 12,121,'Door',1,30,'Manufacture the door' 
INSERT INTO @Table SELECT 12,122,'Window',2,10,'Manufacture the window' 
INSERT INTO @Table SELECT 2,11,'Wheel',2,15,'Assembly the wheel'

;WITH Vals AS (
        SELECT  *,
                qty Level_Qty,
                CAST(id AS VARCHAR(MAX)) + '\' AS [LEVEL]
        FROM    @Table
        WHERE   parentId IS NULL
        UNION ALL
        SELECT  t.*,                
                p.qty * t.qty Level_Qty,
                CAST(p.[LEVEL] AS VARCHAR(MAX))  + CAST(t.id AS VARCHAR(MAX)) + '\' AS [LEVEL]
        FROM    @Table t INNER JOIN
                Vals p  ON  p.Id = t.parentId
)
SELECT  *,
        (SELECT SUM(Level_Qty * manufacturingCost) FROM Vals WHERE [Level] LIKE v.[LEVEL] + '%') / Level_Qty
FROM    Vals v
ORDER BY [LEVEL]

SQL 小提琴示例 http://www.sqlfiddle.com/#!3/d41d8/4562/0

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQL Server 2008 中的 CTE:如何递归计算小计 的相关文章

  • 为什么Asp.net MVC4不能使用SQL Server Session状态存储的cookieless

    全部 这是我在 Asp net MVC4 应用程序中的 Web 配置 我发现如果我将 cookieless 设置为 false 一切都会正常 但如果我不想使用 cookie 那么应用程序就无法工作 当我调试应用程序时 我发现控制器无法接收来
  • 用于将字符串与通配符模式进行匹配的递归函数

    所以我一整天都在试图解决这个作业 只是无法完成 以下函数接受 2 个字符串 第二个 不是第一个 可能包含 的 星号 An 是字符串的替换 空 1个字符或更多 它可以出现 仅在s2中 一次 两次 更多或根本不出现 它不能与另一个相邻 ab c
  • Haskell:处理死锁的自引用列表

    GHC 允许永久阻止以下内容是否有任何有用的理由 list 1 tail list 看起来列表迭代器 生成器有点复杂 我们应该能够做一些更有用的事情 Return error Infinitely blocking list Return
  • 使用 Excel 创建包含特殊字符的 CSV 文件,然后使用 SSIS 将其导入数据库

    获取此 XLS 文件 然后 我将此 XLS 文件另存为 CSV 然后使用文本编辑器将其打开 这是我所看到的 Col1 Col2 Col3 Col4 Col5 Col6 Col7 1 ABC AB C D E F 03 3 2 我看到 C 列
  • 到命名实例的 Sql 连接字符串

    我可以在示例代码项目中使用它连接到我的 sql server 2008 开发人员服务器 string connection data source SQLSERVER2008 Integrated Security SSPI Initial
  • 是否可以使用 jquery $.ajax 添加、删除 xml 节点?

    我想用jquery删除一些节点或者在xml中添加一些节点 我尝试用append empty remove但所有这些似乎都不起作用 喜欢 在 ajax 中 success function xml xml find layout append
  • 如何根据事件触发SSRS订阅?

    有没有一种方法可以让我在共享文件夹中创建文件等事件时触发 SSRS 订阅 基于时间 我们可以使用 powershell 或 C 来实现吗 SSRS 中是否有可用的开箱即用功能 尽管我认为没有 我正在使用 SQL Server 2008 R2
  • SQL Server 列的默认值

    当您使用列的默认值时SQL Server Management Studio表设计器 SSMS 更改您的默认值并在其周围添加括号 在所有版本和 SQL Server 的所有版本中 例如 如果您设置0作为默认值 此默认值更改为 0 我不知道为
  • 而不是SQL Server中的触发器丢失SCOPE_IDENTITY?

    我有一个表 我在其中创建了一个INSTEAD OF触发执行一些业务规则 问题是当我将数据插入该表时 SCOPE IDENTITY 返回一个NULL值 而不是实际插入的身份 插入 范围代码 INSERT INTO dbo Payment Da
  • 为什么haskell中的递归列表这么慢?

    我对 Haskell 很陌生 我在 Haskell 中定义了一个函数 febs Integral a gt a gt a febs n n lt 0 0 n 1 1 n 2 1 otherwise febs n 1 febs n 2 但是
  • 在 Java 中实现 SQL CHECKSUM

    我在 SQL Server 2008 中有一个现有数据库 它通过存储过程为现有 PHP Web 应用程序执行用户身份验证 Web 应用程序向存储过程发送一个字符串 无论存储过程如何存储 并使用 SQL Checksum 检查该值 http
  • SQL - 我需要将总值划分为另一个表中的多行

    假设我在 SQL Server 2008 中有以下表 学校桌 School Id Course Id Total Students 1 Acct101 150 1 Acct102 100 2 Acct101 110 2 Acct102 13
  • 无法附加数据库或创建新数据库 - SQL Server 2008 [重复]

    这个问题在这里已经有答案了 可能的重复 SQL Server 2008 Express 无法附加 mdf 文件 https stackoverflow com questions 1424811 sql server 2008 expres
  • 与 PostgreSQL CTE 的一般并行性

    我正在处理一些大数据 并且在查询中获取并行计划是必要的 我也很喜欢使用 CTE 来表达我的查询 但根据 PostgreSQL 的文档 我不太确定 CTE 是否对并行性造成严重限制 Here https www postgresql org
  • 正则表达式引擎如何解析具有递归子模式的正则表达式?

    此正则表达式匹配回文 1 2 我无法理解它是如何工作的 递归何时结束 以及正则表达式何时从递归子模式中断并转到 part Thanks 编辑 抱歉我没有解释 2 and 1 1 指第一个子模式 对其自身 2 反向引用第二个子模式的匹配 即
  • TSQL 返回 NO 或 YES,而不是 TRUE 或 FALSE

    如果某些列返回 FALSE 如何显示不同的值 例如 COLUMN BASIC 返回 FALSE 但我需要向用户显示 YES 或 NO 情况为 FALSE 返回 NO 如果是 varchar 或 bit 则处理 NULL case when
  • SQL Server 2008 R2 的 Try_Convert

    我正在使用 SQL Server 2008 R2 并且有一个VARCHAR我想要转换为的列DECIMAL 28 10 using CONVERT 但其中许多行的格式错误 因此无法将它们解析为数字 在这种情况下 我只想通过将结果设置为 0 或
  • 使用 Python 的“哈密尔顿”路径

    我正在尝试使用 Python 实现遍历所有图顶点的任意路径 不一定是循环 的递归搜索 这是我的代码 def hamilton G size pt path if pt not in set path path append pt if le
  • 根据表sql中的行替换字符串中的字符

    我需要用一些映射的字符替换字符串中的字符列表 我有一个表 dbo CharacterMappings 有 2 列 CharacterToFilter 和 ReplacementCharacter 假设这个表中有3条记录 Filter Rep
  • 递归中的收益回报

    我正在尝试创建一个 IEnumrable

随机推荐