【问题标题】:Recursive CTE Bill of Materials递归 CTE 物料清单
【发布时间】:2014-04-14 04:39:51
【问题描述】:

这是我的第一个问题,如果我不够清楚,请原谅我。

我的任务是获取装配(材料清单)的所有组件的总成本。基本上,我想查询包含组件采购订单分配的表,以便获取当前与未发布装配相关的成本。

这很棘手,因为程序集的组件可能是程序集本身,在这种情况下,我需要查询另一个表,该表包含有关其他程序集是否链接到该主程序集的信息。 (我进行了检查以确保不会发生过度分配,但可能还没有分配任何东西,这没关系)在这种情况下,查询采购订单分配表以获取该装配编号的组件,并将这些成本添加到父程序集的总计。

我第一次使用 CTE,但运气不佳。谁能帮助确定我在这里做错了什么?

锚将所有组件(不包括子组件)以及它们的单位成本和数量从我试图确定成本的主组件的采购订单中拉入。

递归部分应该为已通过存在于 BM10200_AssemblyQtyDetail 表中“链接”的组件提取组件、成本和数量。如果父组件在 TRANNUM 列中,则该行的 TRX_ID 是作为主组件的子组件组件的链接组件。

USE HT
GO
WITH BOMCost (Assembly, Component, PriceFromPO, Qty, BOMLevel)
AS
(
-- Anchor member definition
SELECT asl.TRX_ID, asl.ITEMNMBR, asl.UNITCOST, asl.SERLTQTY,
0 AS BOMLevel
FROM HT.DBO.BM10400 AS asl
WHERE asl.TRX_ID = 'ASM0002909'
UNION ALL
-- Recursive member definition
SELECT asl.TRX_ID, asl.ITEMNMBR, asl.UNITCOST, asl.SERLTQTY,
    BOMLevel + 1
FROM HT.DBO.BM10400 AS asl
INNER JOIN HT.DBO.BM10200_AssemblyQtyDetail AS bqd 
    ON asl.TRX_ID = bqd.TRANNUM
INNER JOIN BOMCost AS bc
    ON bqd.TRX_ID = bc.Assembly
)


-- Statement that executes the CTE
SELECT Assembly, Component, PriceFromPO, Qty, BOMLevel
FROM BOMCost

重申一下,这里的问题是这只返回主组件的组件,没有任何子组件相关的成本。所以只是顶层的组件。我在链接表中有一条记录,将这个 BM 的子装配的装配链接到主装配,但它不会拉取该装配编号的组件。我认为这可能与递归部分连接有关。任何帮助表示赞赏!

这是数据场景。 ASM0002909 是一个组件,其组件本身就是一个组件。 ASM0002914 正在同时为 ASM0002909 构建,它本身有两个组件。我只想获取从 PO 实际收到的费用,因此其他组件是否需要但尚未收到并不重要。以下是所有内容的总和 (SERLTQTY * UNITCOST),以获得主组件的总成本。

然而,这是我目前从查询中得到的结果。它应该运行一次递归步骤并返回 ASM0002914 结果。

我已经使用两个主表、数据和我当前使用的 sql 查询设置了一个 sqlfiddle,它仍然没有拾取子组件组件并返回一个超出递归限制的错误。 http://sqlfiddle.com/#!3/bd1b98/6

【问题讨论】:

  • 我认为您需要在此处发布一些示例数据以使其更清晰。
  • 你能用你的表和你目前拥有的东西创建一个sqlfiddle吗?
  • 第一次使用 sqlfiddle,请给我一点答案。
  • 这是 sqlfiddle sqlfiddle.com/#!3/bd1b98/6

标签: sql sql-server recursion common-table-expression


【解决方案1】:

我可能遗漏了一些东西,但您的 JOIN 标准似乎排除了递归:

INNER JOIN BOMCost AS bc ON bqd.TRX_ID = bc.Assembly

ASM0002909 不等于 ASM0002914,因此底部没有结果。

更新:

WITH BOMCost (Assembly, Component, PriceFromPO, Qty, BOMLevel)
AS
(
-- Anchor member definition
    SELECT asl.TRX_ID, asl.ITEMNMBR, asl.UNITCOST, asl.SERLTQTY,
    0 AS BOMLevel
    FROM DBO.BM10400 AS asl
    WHERE asl.TRX_ID = 'ASM0002909'
    UNION  ALL
-- Recursive member definition
    SELECT asl.TRX_ID, asl.ITEMNMBR, asl.UNITCOST, asl.SERLTQTY,
        BOMLevel + 1
    FROM DBO.BM10400 AS asl
    INNER JOIN DBO.BM10200_AssemblyQtyDetail AS bqd 
        ON asl.TRX_ID = bqd.TRX_ID
    INNER JOIN BOMCost AS bc
        ON bqd.TRANNUM = bc.Assembly

)


-- Statement that executes the CTE
SELECT DISTINCT Assembly, Component, PriceFromPO, Qty, BOMLevel
FROM BOMCost

演示:SQL Fiddle

【讨论】:

  • 我相信你是对的,这就解释了为什么我只从主播那里获取记录。我只是不确定如何正确加入它并使用 TRANNUM 列与 asl.TRX_ID 匹配的 TRX_ID 列从 BM10400 获取结果
  • 在不知道表结构的情况下很难找出答案,您最好添加另一个具有父/子 trx_id 字段的 cte。
  • Goat to 你的意思是 ParentAssembly 和 SubAssembly 这样的两列?此外,一旦我将内部连接引用更改为 cte,我就会开始遇到最大递归错误。请查看 sqlfiddle!感谢您的帮助
  • @Dezryth 几乎把它放在了你的小提琴中,只需要稍微改变一下连接标准。这里的问题是锚中的每个元素都将连接到递归部分中的两条记录。所以我加了DISTINCT
猜你喜欢
  • 2013-08-27
  • 2014-04-10
  • 2012-03-29
  • 2020-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-30
相关资源
最近更新 更多