在递归公用表表达式的递归部分中不允许使用TOP或OFFSET运算符

时间:2017-01-20 18:57:57

标签: sql sql-server

我尝试使用递归CTE查询创建一个已计算成本的物料清单。我遇到的问题是我需要为材料零件选择单个零件版本,但递归查询不允许使用TOP运算符。 提供有关该问题的更多信息:

  • 零件版本(PartRev表)具有由多种材料(PartMtl表)组成的物料清单。
  • 物料清单上的材料也可能有自己的材料。为了得到这个,我们需要材料部分(已经有了)和它的修订。但是,我们的ERP系统没有记录物料部分修订(我们没有开发ERP系统,所以我们无法改变这一点)。它是在动态计算并选择一条记录。
  • SQL Server不允许在递归查询中使用TOP运算符,因此我无法选择单个修订版。

我不确定我能做些什么来解决这个问题。下面是我尝试的SQL代码。

WITH CostedBOMFinance AS
(
select 
    Erp.PartRev.PartNum, 
    Erp.PartRev.RevisionNum,
    case when Erp.PartMtl.ViewAsAsm = 1 then 'Asm' else 'Mtl' end as MtlType,
    Erp.PartMtl.MtlSeq as Seq,
    Erp.PartMtl.MtlPartNum,
    (
        select TOP(1) Erp.PartRev.RevisionNum
        from Erp.PartRev as MtlRev
        where MtlRev.Approved = 1 and
              MtlRev.PartNum = Erp.PartMtl.MtlPartNum
    ) as MtlRev,
    Erp.Part.PartDescription,
    Erp.PartMtl.QtyPer,
    Erp.PartMtl.UOMCode,
    Erp.PartCost.StdBurdenCost,
    Erp.PartCost.StdLaborCost,
    Erp.PartCost.StdMaterialCost as StdUnitCost,
    Erp.PartCost.StdSubContCost,
    Erp.PartCost.StdBurdenCost + Erp.PartCost.StdLaborCost + Erp.PartCost.StdMaterialCost + Erp.PartCost.StdSubContCost as TotalStdCost,
    1 as Level
from Erp.PartRev
join Erp.PartMtl on Erp.PartMtl.Company = Erp.PartRev.Company and
                    Erp.PartMtl.PartNum = Erp.PartRev.PartNum and
                    Erp.PartMtl.RevisionNum = Erp.PartRev.RevisionNum
join Erp.Part on Erp.Part.Company = Erp.PartMtl.Company and
                 Erp.Part.PartNum = Erp.PartMtl.MtlPartNum
join Erp.PartCost on Erp.PartCost.Company = Erp.Part.Company and
                     Erp.PartCost.PartNum = Erp.Part.PartNum

UNION ALL

select 
    Erp.PartRev.PartNum, 
    Erp.PartRev.RevisionNum,
    case when Erp.PartMtl.ViewAsAsm = 1 then 'Asm' else 'Mtl' end as MtlType,
    Erp.PartMtl.MtlSeq as Seq,
    Erp.PartMtl.MtlPartNum,
    (
        select TOP(1) MtlRev.RevisionNum
        from Erp.PartRev as MtlRev
        where MtlRev.Approved = 1 and
              MtlRev.PartNum = Erp.PartMtl.MtlPartNum
    ) as MtlRev,
    Erp.Part.PartDescription,
    Erp.PartMtl.QtyPer,
    Erp.PartMtl.UOMCode,
    Erp.PartCost.StdBurdenCost,
    Erp.PartCost.StdLaborCost,
    Erp.PartCost.StdMaterialCost as StdUnitCost,
    Erp.PartCost.StdSubContCost,
    Erp.PartCost.StdBurdenCost + Erp.PartCost.StdLaborCost + Erp.PartCost.StdMaterialCost + Erp.PartCost.StdSubContCost as TotalStdCost,
    Level + 1
from Erp.PartRev
join Erp.PartMtl on Erp.PartMtl.Company = Erp.PartRev.Company and
                    Erp.PartMtl.PartNum = Erp.PartRev.PartNum and
                    Erp.PartMtl.RevisionNum = Erp.PartRev.RevisionNum
join Erp.Part on Erp.Part.Company = Erp.PartMtl.Company and
                 Erp.Part.PartNum = Erp.PartMtl.MtlPartNum
join Erp.PartCost on Erp.PartCost.Company = Erp.Part.Company and
                     Erp.PartCost.PartNum = Erp.Part.PartNum
join CostedBOMFinance as CostedBOMFinanceParent on CostedBOMFinanceParent.PartNum = Erp.PartMtl.MtlPartNum and
                                                CostedBOMFinanceParent.RevisionNum = MtlRev
)

select * from CostedBOMFinance

1 个答案:

答案 0 :(得分:3)

您需要使用窗口函数,在这种情况下,您可以在您加入的子查询中使用它,如下所示:

SELECT 
-- ...
  MtlRev.RevisionNum,
-- ...
from Erp.PartRev
join (
  select RevisionNum, PartNum,
         ROW_NUMBER() OVER (Partition By PartNum ORDER BY RevisionNum) AS RN
  from Erp.PartRev as MtlRev
  where MtlRev.Approved = 1
) AS MtlRev ON MtlRev.PartNum = Erp.PartMtl.MtlPartNum and MtlRev.RN = 1
-- ...
  

注意:您可能需要完全ORDER BY RevisionNum DESC或其他一些订单,我不知道,因为您没有说。