物料清单的递归查询

Lea*_*rve 5 sql recursion sql-server-2012

我最近才开始自学 SQL,并且能够从各种教程中拼凑出我需要的几乎所有东西,但是这个教程让我头撞墙。我们有一个表格,其中包含我们产品的所有物料清单信息。我只需要其中的 4 列 - PPN_I、CPN_I、QUANTITY_I、BOMNAME_I - 它们分别是项目编号、原材料编号、数量和 BOMName。许多 BOM 包含子装配体。我需要一个结果集,列出 BOM 的所有组件,而不考虑级别。我很确定我需要使用递归查询,但不能完全得到它,任何帮助将不胜感激。我知道还有其他几个 BOM 问题,但所有这些问题似乎都有不同的表结构。所以 -

首先,我只是想获得一个特定项目的结果,以方便我的猜测和检查工作。完成后,我需要所有项目的报告,或者至少是项目列表。其中许多项目都是可配置的,并且具有多个 BOM。为了获得默认设置,我正在寻找一个空白的 BOM 名称。

我可以运行它并获得第一级:

    select bm.ppn_i, bm.cpn_i, bm.bomname_i, bm.QUANTITY_I, 1 as BOMLevel
    from BM010115 bm
    where bm.PPN_I like '0123105-HWT' and bm.BOMNAME_I like ''
Run Code Online (Sandbox Code Playgroud)

问题是一个(或多个)行将具有作为子部件的 cpn_i 值。要查看子组件的组成部分,我需要将第一个查询的每个结果放回同一个查询中。

    select bm.ppn_i, bm.cpn_i, bm.bomname_i, bm.QUANTITY_I, 2 as BOMLevel
    from BM010115 bm
    where bm.PPN_I like 'ZC-BASESUBLIM' and bm.BOMNAME_I like ''
Run Code Online (Sandbox Code Playgroud)

显然,这不是最有效的方法。我试过了,我也试过了,但我似乎无法得到正确的结果。我已经经历了很多不同的版本,这是我最近做的/最接近的。

    With BMStudy as
    (select bm.ppn_i, bm.cpn_i, bm.bomname_i, bm.QUANTITY_I, 1 as BOMLevel
    from BM010115 bm
    where bm.PPN_I like '0123105-HWT' and bm.BOMNAME_I like ''

    UNION ALL

    select bb.ppn_i, ba.cpn_i, bb.bomname_i, ba.quantity_i, 2 as BOMLevel
    from BM010115 bb, BMStudy ba
    where bb.BOMNAME_I like '' and ba.PPN_I = bb.CPN_I)
    select * from BMStudy
Run Code Online (Sandbox Code Playgroud)

这仅返回第一级结果。我不相信任何 BOM 的深度都超过 3 个级别,但我希望有一列指示它是哪个级别。有人可以指出我正确的方向或给我一些关于我哪里出错的提示吗?

TL;DR - 需要提取 BOM 中所有组件的查询,然后为第一个查询的所有结果提取 BOM 组件并将其添加到结果集中。


谢谢

Gor*_*off 5

我觉得你的逻辑基本没问题。这里有两个改进。首先,级别是递增的,因此您可以看到递归会发生什么。其次,它使用显式连接:

With BMStudy as (
      select bm.ppn_i, bm.cpn_i, bm.bomname_i, bm.QUANTITY_I, 1 as BOMLevel
      from BM010115 bm
      where bm.PPN_I like '0123105-HWT' and bm.BOMNAME_I like ''
      UNION ALL
      select bb.ppn_i, ba.cpn_i, bb.bomname_i, ba.quantity_i, (BOMLevel + 1) as BOMLevel
      from BMStudy ba join
           BM010115 bb
           on ba.cpn_i = bb.ppn_i
      where bb.BOMNAME_I like ''
     )
select * from BMStudy;
Run Code Online (Sandbox Code Playgroud)

我怀疑你的问题是条件where bb.BOMNAME_I like ''。这个值有可能是真的NULL而不是空白吗?

您还应该检查这个非递归的一级向下查询的作用:

      select bb.ppn_i, ba.cpn_i, bb.bomname_i, ba.quantity_i, (BOMLevel + 1) as BOMLevel
      from BM010115 ba join
           BM010115 bb
           on ba.cpn_i = bb.ppn_i
      where bb.BOMNAME_I like '' and
            (ba.PPN_I like '0123105-HWT' and ba.BOMNAME_I like '')
Run Code Online (Sandbox Code Playgroud)


Lea*_*rve 2

我对你的帮助感激不尽,戈登。您帮助我解决了一些基本缺陷,我完成了一些调整,并且大部分都满足了我的需要……至少现在是这样。这已经让我发疯有一段时间了。我确定的代码如下,以防对其他人有所帮助

  With BMStudy as (
  select bm.ppn_i, bm.cpn_i, bm.bomname_i, bm.QUANTITY_I, 1 as BOMLevel
  from BM010115 bm
  where bm.PPN_I like '0123105-HWT' and bm.BOMNAME_I like ''
  UNION ALL
  select ba.ppn_i, bb.cpn_i, bb.bomname_i, bb.quantity_i, 
  (BOMLevel + 1) as BOMLevel
  from BMStudy ba join
       BM010115 bb
       on ba.cpn_i = bb.ppn_i
  where bb.BOMNAME_I like ''
 )

 select top 1000 BMStudy.*, i.ITEMDESC from BMStudy, iv00101 i
 where CPN_I = itemnmbr
 order by BOMLEVEL, CPN_I ASC
 OPTION (MAXRECURSION 0)
Run Code Online (Sandbox Code Playgroud)

再次感谢!