Types don't match between the anchor and the recursive part

,

I’ve got a CTE where I’m multiplying an initial cost (decimal) by a quantity (decimal), to get a decimal value. For some reason I am getting the error “Types don’t match between the anchor and the recursive part”. I have tried making the formats identical, but is there something I am missing? Do I need to cast/convert to a specifically formatted decimal? If I remove the quantity from the formula it works fine, so I must be some sort of mismatch, though if they’re both decimals I don’t see what the issue is.

can you post the sql.

I am guessing your initial value is 0 and the query thinks it is an int.

with [SubQuery1] as 
(select 
	[PartMtl].[Company] as [PartMtl_Company],
	[PartMtl].[PartNum] as [PartMtl_PartNum],
	[PartMtl].[RevisionNum] as [PartMtl_RevisionNum],
	[PartMtl].[MtlSeq] as [PartMtl_MtlSeq],
	[PartMtl].[MtlPartNum] as [PartMtl_MtlPartNum],
	[PartMtl].[QtyPer] as [PartMtl_QtyPer],
	[PartMtl].[RelatedOperation] as [PartMtl_RelatedOperation],
	(0) as [Calculated_Hierarchy],
	(cast ( substring('........',1 , (Hierarchy + 1) ) + PartMtl.PartNum as nvarchar(25))) as [Calculated_Ind1],
	(case
     when PartCost.PartNum = @PartNum then         
     PartMtl.QtyPer * ( PartCost.StdLaborCost + PartCost.StdBurdenCost + PartCost.StdMaterialCost + PartCost.StdSubContCost + PartCost.StdMtlBurCost )
     else 0
 end) as [Calculated_InitialCost]
from Erp.PartMtl as PartMtl
inner join Erp.PartRev as PartRev on 
	PartMtl.Company = PartRev.Company
	and PartMtl.PartNum = PartRev.PartNum
	and PartMtl.RevisionNum = PartRev.RevisionNum
	and PartMtl.AltMethod = PartRev.AltMethod
	and ( PartRev.Approved = true  )

inner join Erp.PartCost as PartCost on 
	PartMtl.Company = PartCost.Company
	and PartMtl.MtlPartNum = PartCost.PartNum
where PartMtl.MtlPartNum = @PartNum

union all
select 
	[PartMtl1].[Company] as [PartMtl1_Company],
	[PartMtl1].[PartNum] as [PartMtl1_PartNum],
	[PartMtl1].[RevisionNum] as [PartMtl1_RevisionNum],
	[PartMtl1].[MtlSeq] as [PartMtl1_MtlSeq],
	[PartMtl1].[MtlPartNum] as [PartMtl1_MtlPartNum],
	[PartMtl1].[QtyPer] as [PartMtl1_QtyPer],
	[PartMtl1].[RelatedOperation] as [PartMtl1_RelatedOperation],
	(SubQuery1.Calculated_Hierarchy + 1) as [Calculated_Hierarchy2],
	(cast ( substring('........',1 , (Hierarchy2 + 1) ) + PartMtl1.PartNum as nvarchar(25))) as [Calculated_Ind2],
	(SubQuery1.Calculated_InitialCost * PartMtl1.QtyPer) as [Calculated_Cost]
from  SubQuery1  as SubQuery1
inner join Erp.PartMtl as PartMtl1 on 
	SubQuery1.PartMtl_Company = PartMtl1.Company
	and SubQuery1.PartMtl_PartNum = PartMtl1.MtlPartNum
inner join Erp.PartRev as PartRev1 on 
	PartMtl1.Company = PartRev1.Company
	and PartMtl1.PartNum = PartRev1.PartNum
	and PartMtl1.RevisionNum = PartRev1.RevisionNum
	and PartMtl1.AltMethod = PartRev1.AltMethod
	and ( PartRev1.Approved = true  ))

select 
	[SubQuery11].[PartMtl_Company] as [PartMtl_Company],
	[SubQuery11].[PartMtl_PartNum] as [PartMtl_PartNum],
	[SubQuery11].[PartMtl_RevisionNum] as [PartMtl_RevisionNum],
	[SubQuery11].[PartMtl_MtlSeq] as [PartMtl_MtlSeq],
	[SubQuery11].[PartMtl_MtlPartNum] as [PartMtl_MtlPartNum],
	[SubQuery11].[PartMtl_QtyPer] as [PartMtl_QtyPer],
	[SubQuery11].[PartMtl_RelatedOperation] as [PartMtl_RelatedOperation]
from  SubQuery1  as SubQuery11

For the Calculated_InitialCost what is the type?

You might need to cast it to decimal

CAST( case
when PartCost.PartNum = @PartNum then
PartMtl.QtyPer * ( PartCost.StdLaborCost + PartCost.StdBurdenCost + PartCost.StdMaterialCost + PartCost.StdSubContCost + PartCost.StdMtlBurCost )
else 0
end as decimal)

I am trying to stack up the total cost of the lowest level part (input parameter) in a BOM. I only care about the lowest level, so my InitialCost formula ignores any parts that aren’t equal to input parameter. That is probably causing an issue because at each recursion it’s trying to multiply that field (which is 0 for any higher levels). This is probably causing the error but also I need to find a way to get that initial cost to be factored in at each level.

Calculated_InitialCost is a decimal.

I applied a cast to both InitialCost and Cost and the error is gone.

Cool. You can always do the costing outside of the CTE. That way you are only referencing the costing tables once vs each time in the loop.

But if you’re not including the costing in the loop, then how can you stack up the cost (there might be 5 washers at the lowest level, but that might go into a part that has a quantity of 2 in the top level, making there 10 washers at the upper level)?

That is driven from your part qty though. The costs is just math based on the qty needed.

by the way I love these types of queries. I am asking as a way to improve, not trying to be critical.

also just letting you know as I got caught with this one. Your query assumes that there is only ONE approved rev for the part. If there are multiple things might not look right. Sounds like you have many levels to BOM this may come into play.

Oh no, I didn’t think you were being critical. This is my first foray into these and so I’m learning a lot. It is likely I could do it outside of the CTE but it’s hard to wrap my head around…not sure it would know which part goes to which.

Keep posting then as you get stuck.

Right now I am trying to only include the most recent revision. Not sure if I can accomplish this without another subquery.

correct it will be a couple of subqueries.

It will end up looking something like this. Granted you will have to make changes for your situation.

with [BOMReviewParent] as 
(select 
	(Part.ShortChar10) as [Calculated_Customer],
	(PartRev.PartNum) as [Calculated_TopPart],
	(PartRev.RevisionNum) as [Calculated_TopPartRev],
	(part.PartNum) as [Calculated_ParentPartNum],
	(PartRev.RevisionNum) as [Calculated_ParentRevNum],
	(part.PartNum) as [Calculated_ChildPartNum],
	(PartRev.RevisionNum) as [Calculated_ChildRevNum],
	(0) as [Calculated_lv],
	(Cast(part.PurchasingFactor as int)) as [Calculated_QtyPer],
	(Cast(part.PartDescription as nvarchar(500))) as [Calculated_PartName],
	(0) as [Calculated_OpSeq],
	(CAST(part.PartNum + '-' + partrev.RevisionNum as nvarchar(500))) as [Calculated_Sort]
from dbo.Part as Part
inner join Erp.PartRev as PartRev on 
	Part.Company = PartRev.Company
	and Part.PartNum = PartRev.PartNum
     and Part.InActive = 0 
  and Part.ClassID in ( 'FGD',  'FGA')
  and PartRev.Approved = 1
union all
select 
	[BOMReviewParent].[Calculated_Customer] as [Calculated_Customer],
	[BOMReviewParent].[Calculated_TopPart] as [Calculated_TopPart],
	[BOMReviewParent].[Calculated_TopPartRev] as [Calculated_TopPartRev],
	[BOMChildren].[PartMtl_PartNum] as [PartMtl_PartNum],
	[BOMChildren].[PartMtl_RevisionNum] as [PartMtl_RevisionNum],
	[BOMChildren].[PartMtl_MtlPartNum] as [PartMtl_MtlPartNum],
	[BOMChildren].[Calculated_RevNum] as [Calculated_RevNum],
	(BOMReviewParent.Calculated_lv + 1) as [Calculated_BOMlv],
	(cast(BOMChildren.Calculated_ChildQtyPer as int)) as [Calculated_BOMQtyPer],
	(CAST(REPLICATE ('|     ' , BOMReviewParent.Calculated_lv +1) + BOMChildren.PartBOMChild_PartDescription as nvarchar(500))) as [Calculated_BOMPartName],
	(BOMChildren.Calculated_MtlSeq) as [Calculated_BOMMtlSeq],
	(CAST(BOMReviewParent.Calculated_Sort + '-' + RIGHT( '0000'+ Convert(varchar, BOMChildren.Calculated_SeqNum), 4)as nvarchar(500))) as [Calculated_BOMSort]
from  (select 
	[PartMtl].[PartNum] as [PartMtl_PartNum],
	[PartMtl].[RevisionNum] as [PartMtl_RevisionNum],
	[PartMtl].[MtlPartNum] as [PartMtl_MtlPartNum],
	(((select 
	[PartRevA].[RevisionNum] as [PartRevA_RevisionNum]
from Erp.PartRev as PartRevA
inner join  (select PartRevB.Company,
	[PartRevB].[PartNum] as [PartRevB_PartNum],
	[PartRevB].[RevisionNum] as [PartRevB_RevisionNum],
	(ROW_NUMBER() OVER (PARTITION BY partrevb.PartNum ORDER BY  partrevb.ApprovedDate DESC)) as [Calculated_PartRevB_RowNum]
from Erp.PartRev as PartRevB
where (PartRevB.Approved = 1  and PartRevB.EffectiveDate <= getdate() and PartRevB.PartNum = [PartMtl].[MtlPartNum] ))  as PartRevB1 on 
	PartRevA.PartNum = PartRevB1.PartRevB_PartNum
	and PartRevA.RevisionNum = PartRevB1.PartRevB_RevisionNum
         and PartRevA.Company = PartRevB1.Company
where PartRevB1.Calculated_PartRevB_RowNum = 1))) as [Calculated_RevNum],
	(cast(PartMtl.QtyPer as int)) as [Calculated_ChildQtyPer],
	[PartBOMChild].[PartDescription] as [PartBOMChild_PartDescription],
	(cast(PartMtl.MtlSeq as nvarchar(254))) as [Calculated_SeqNum],
	(CAST(PartMtl.MtlSeq as Int)) as [Calculated_MtlSeq]
from Erp.PartMtl as PartMtl
inner join dbo.Part as PartBOMChild on 
	PartMtl.Company = PartBOMChild.Company
	and PartMtl.MtlPartNum = PartBOMChild.PartNum)  as BOMChildren
inner join  BOMReviewParent  as BOMReviewParent on 
	BOMChildren.PartMtl_PartNum = BOMReviewParent.Calculated_ChildPartNum
	and BOMChildren.PartMtl_RevisionNum = BOMReviewParent.Calculated_ChildRevNum)

When I run the query I am getting zero records…not sure what I’m doing wrong.

with [SubQuery1] as 
(select 
	[PartMtl].[Company] as [PartMtl_Company],
	[PartMtl].[PartNum] as [PartMtl_PartNum],
	[MaxEffDate2].[PartRev3_RevisionNum] as [PartRev3_RevisionNum],
	[PartMtl].[MtlSeq] as [PartMtl_MtlSeq],
	[PartMtl].[MtlPartNum] as [PartMtl_MtlPartNum],
	[PartMtl].[QtyPer] as [PartMtl_QtyPer],
	[PartMtl].[RelatedOperation] as [PartMtl_RelatedOperation],
	(0) as [Calculated_Hierarchy],
	(cast ( substring('........',1 , (Hierarchy + 1) ) + PartMtl.PartNum as nvarchar(25))) as [Calculated_Ind1],
	(cast(case
     when PartCost.PartNum = @PartNum then         
     PartMtl.QtyPer * ( PartCost.StdLaborCost + PartCost.StdBurdenCost + PartCost.StdMaterialCost + PartCost.StdSubContCost + PartCost.StdMtlBurCost )
     else 0
 end as decimal(10,2))) as [Calculated_InitialCost],
	(cast(PartMtl.QtyPer as decimal(10,2))) as [Calculated_Qty]
from Erp.PartMtl as PartMtl
inner join Erp.PartCost as PartCost on 
	PartMtl.Company = PartCost.Company
	and PartMtl.MtlPartNum = PartCost.PartNum
where PartMtl.MtlPartNum = @PartNum

union all
select 
	[PartMtl1].[Company] as [PartMtl1_Company],
	[PartMtl1].[PartNum] as [PartMtl1_PartNum],
	[PartMtl1].[RevisionNum] as [PartMtl1_RevisionNum],
	[PartMtl1].[MtlSeq] as [PartMtl1_MtlSeq],
	[PartMtl1].[MtlPartNum] as [PartMtl1_MtlPartNum],
	[PartMtl1].[QtyPer] as [PartMtl1_QtyPer],
	[PartMtl1].[RelatedOperation] as [PartMtl1_RelatedOperation],
	(SubQuery1.Calculated_Hierarchy + 1) as [Calculated_Hierarchy2],
	(cast ( substring('........',1 , (Hierarchy2 + 1) ) + PartMtl1.PartNum as nvarchar(25))) as [Calculated_Ind2],
	(cast(SubQuery1.Calculated_InitialCost * PartMtl1.QtyPer as decimal(10,2))) as [Calculated_Cost],
	(cast(SubQuery1.PartMtl_QtyPer * PartMtl1.QtyPer as decimal (10,2))) as [Calculated_Qty]
from  SubQuery1  as SubQuery1
inner join Erp.PartMtl as PartMtl1 on 
	SubQuery1.PartMtl_Company = PartMtl1.Company
	and SubQuery1.PartMtl_PartNum = PartMtl1.PartNum
	and SubQuery1.PartRev3_RevisionNum = PartMtl1.RevisionNum)

select 
	[SubQuery11].[PartMtl_Company] as [PartMtl_Company],
	[SubQuery11].[PartMtl_PartNum] as [PartMtl_PartNum],
	[SubQuery11].[PartRev3_RevisionNum] as [PartRev3_RevisionNum],
	[SubQuery11].[PartMtl_MtlSeq] as [PartMtl_MtlSeq],
	[SubQuery11].[PartMtl_MtlPartNum] as [PartMtl_MtlPartNum],
	[SubQuery11].[PartMtl_QtyPer] as [PartMtl_QtyPer],
	[SubQuery11].[PartMtl_RelatedOperation] as [PartMtl_RelatedOperation],
	[SubQuery11].[Calculated_Hierarchy] as [Calculated_Hierarchy],
	[SubQuery11].[Calculated_Ind1] as [Calculated_Ind1],
	(case 
     when PartCost1.PartNum = @PartNum then
     PartCost1.StdLaborCost + PartCost1.StdBurdenCost + PartCost1.StdMaterialCost + PartCost1.StdSubContCost + PartCost1.StdMtlBurCost
     else 0
 end) as [Calculated_UnitCost],
	[SubQuery11].[Calculated_InitialCost] as [Calculated_InitialCost],
	[SubQuery11].[Calculated_Qty] as [Calculated_Qty]
from  SubQuery1  as SubQuery11
inner join Erp.PartCost as PartCost1 on 
	SubQuery11.PartMtl_Company = PartCost1.Company
	and SubQuery11.PartMtl_MtlPartNum = PartCost1.PartNum

Part of my problem was I was putting a part number in that didn’t have any parent parts, but I ended up moving the “most recent revision” subquery to the top level.