外部引用来限制内部组

Posted

技术标签:

【中文标题】外部引用来限制内部组【英文标题】:Outer reference to restrict inner group by 【发布时间】:2021-04-15 14:12:13 【问题描述】:

我有一系列接收和发出交易。收到的库存可以以每个作业材料项目的不同成本计算,可能在多个交易中收到。并且有两种可能的收货方式:Mfg Receipt 和 Receipt Lines。如果两者都不存在,则成本默认为平均库存成本,该成本可靠地存储在成本类型中。收到的成本没有可靠地存储在问题交易的成本类型中,所以我必须在收据交易中向后搜索。此优先级由 COALESCE 处理。

目的是以收到货时相同的成本将发货退回(反向)到库存。后续收货是可能的,但成本不同,退货应按该成本计算,而不是同一作业中之前或后续收货的成本。

加入成本类型(前缀 int)的事务(前缀 imt)对于 Material ID 21 如下所示:

每个 MaterialIssue 事务都可以与每个 Receipt Lines 配对,因此我必须将内部结果限制为单个接收事务以防止笛卡尔积,没有它,我可以获得多个结果,如材料项 21:

我曾尝试使用 ROW() 排名来完成此 CTE,并使用想象中的所需方法进行评论,但它令人费解,我不知道如何去做:

DECLARE @bShowNonInventory BIT = 1
DECLARE @nCostingMethod INT = 1
DECLARE @vJobID VARCHAR (11) = '23532-02-01'
; WITH
MaterialIssues as (
                    SELECT 
                    MI.imtJobID JobID
                    , MI.imtJobAssemblyID AssemblyID
                    , MI.imtJobMaterialID MaterialID
                    , SUM(
                        (
                        COALESCE(
                            MR.intActualUnitMaterialCost 
                            , RL.intActualUnitMaterialCost 
                            , intUnitMaterialCost
                        ) 

                    ) 
                    * - (intQuantity)
                ) NetCost
                FROM PartTransactions MI -- Material Issue
                INNER JOIN PartTransactionCosts
                    ON imtPartTransactionID = intPartTransactionID


                LEFT JOIN /* get single, most recent received cost */
                    (   SELECT * FROM 
                        (
                            SELECT 
                            imtJobID, imtJobAssemblyID, imtJobMaterialID
                            , imtPartTransactionID
                            , intActualUnitMaterialCost
                            , ROW_Number() 
                               OVER (Partition by imtJobID, imtJobAssemblyID, imtJobMaterialID 
                               Order by imtPartTransactionID DESC) as rn
                               --^ set of results from ranking too broad
                            FROM PartTransactionCosts
                            JOIN PartTransactions
                                on imtPartTransactionID=intPartTransactionID
                            WHERE imtTableName='MfgReceipts'
                            AND intCostType = 4
                            --< need outer reference here somehow: imtPartTransactionID < (earlier) MI.imtPartTransactionID
                        ) as d 
                    WHERE   rn=1
                    
                    ) MR -- Receipt by Mfg Receipt
                    ON  MI.imtJobID=MR.imtJobID 
                    AND MI.imtJobAssemblyID=MR.imtJobAssemblyID
                    AND MI.imtJobMaterialID=MR.imtJobMaterialID

                    AND MR.imtPartTransactionID < MI.imtPartTransactionID --< dubious restriction on inner result

                LEFT JOIN 
                    (   SELECT * FROM 
                        (
                            SELECT imtJobID, imtJobAssemblyID, imtJobMaterialID
                            , intActualUnitMaterialCost, imtPartTransactionID 
                            , ROW_Number() 
                               OVER (Partition by imtJobID, imtJobAssemblyID, imtJobMaterialID 
                               Order by imtPartTransactionID DESC) as rn
                            FROM PartTransactionCosts
                            JOIN PartTransactions
                                on imtPartTransactionID=intPartTransactionID
                            WHERE imtTableName='ReceiptLines'
                            AND intCostType = 4
                            --< need outer reference here somehow: imtPartTransactionID < (earlier) MI.imtPartTransactionID
                        ) as d 
                    WHERE rn=1 
                    ) RL -- Receipt by ReceiptLine
                    ON  MI.imtJobID=RL.imtJobID 
                    AND MI.imtJobAssemblyID=RL.imtJobAssemblyID
                    AND MI.imtJobMaterialID=RL.imtJobMaterialID

                    AND RL.imtPartTransactionID < MI.imtPartTransactionID --< dubious restriction on inner result

                WHERE 
                        imtSource = 3
                    AND imtNonInventoryTransaction <= @bShowNonInventory                       
                    
                    AND intCostType = @nCostingMethod
                            
                GROUP BY MI.imtJobID 
                    , MI.imtJobAssemblyID 
                    , MI.imtJobMaterialID 
)
-- test query:
Select * from 

MaterialIssues
WHERE JobID = @vJobID

请注意,此问题与Restricting inner query with outer query atttribute 非常相似 - 但我没有看到将内部集限制为一个最近但不是后续结果的要求。

总而言之,项目 21 的接收和(退货)数量的净结果为零,但净成本也应为零,但不正确。

提前感谢您的建议。

编辑:DDL 和示例数据:

USE [master]
GO

CREATE DATABASE [test]
 CONTAINMENT = NONE
 ON  PRIMARY 
( NAME = N'test', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\test.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
 LOG ON 
( NAME = N'test_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\test_log.ldf' , SIZE = 199680KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO

USE test 

CREATE TABLE [test].dbo.[PartTransactions](
    [imtPartTransactionID] [int] NOT NULL,
    [imtTableName] [nvarchar](30) NOT NULL,
    [imtTransactionType] [tinyint] NOT NULL,
    [imtSource] [tinyint] NOT NULL,
    [imtNonInventoryTransaction] [bit] NOT NULL,
    [imtJobID] [nvarchar](20) NOT NULL,
    [imtJobAssemblyID] [int] NOT NULL,
    [imtJobMaterialID] [int] NOT NULL,
    [imtPartID] [nvarchar](30) NOT NULL,

) ON [PRIMARY]
GO
CREATE TABLE [test].[dbo].[PartTransactionCosts](
    [intPartTransactionID] [int] NOT NULL,
    [intPartTransactionCostID] [int] NOT NULL,
    [intCostType] [tinyint] NOT NULL,
    [intQuantity] [numeric](15, 5) NOT NULL,
    [intUnitMaterialCost] [numeric](15, 5) NOT NULL,
    [intActualUnitMaterialCost] [numeric](15, 5) NOT NULL,
) ON [PRIMARY]
GO
-- USE [test]
GO
INSERT [dbo].[PartTransactions] ([imtPartTransactionID], [imtTableName], [imtTransactionType], [imtSource], [imtNonInventoryTransaction], [imtJobID], [imtJobAssemblyID], [imtJobMaterialID], [imtPartID]) VALUES (117718, N'MaterialIssueLines', 2, 3, 0, N'23532-02-01', 0, 21, N'26271/2GC')
GO
INSERT [dbo].[PartTransactions] ([imtPartTransactionID], [imtTableName], [imtTransactionType], [imtSource], [imtNonInventoryTransaction], [imtJobID], [imtJobAssemblyID], [imtJobMaterialID], [imtPartID]) VALUES (117719, N'MfgReceipts', 1, 2, 1, N'23532-02-01', 0, 21, N'26271/2GC')
GO
INSERT [dbo].[PartTransactions] ([imtPartTransactionID], [imtTableName], [imtTransactionType], [imtSource], [imtNonInventoryTransaction], [imtJobID], [imtJobAssemblyID], [imtJobMaterialID], [imtPartID]) VALUES (117726, N'MaterialIssueLines', 2, 3, 0, N'23532-02-01', 0, 21, N'26271/2GC')
GO
INSERT [dbo].[PartTransactions] ([imtPartTransactionID], [imtTableName], [imtTransactionType], [imtSource], [imtNonInventoryTransaction], [imtJobID], [imtJobAssemblyID], [imtJobMaterialID], [imtPartID]) VALUES (117725, N'MfgReceipts', 1, 2, 1, N'23532-02-01', 0, 21, N'26271/2GC')
GO
INSERT [dbo].[PartTransactions] ([imtPartTransactionID], [imtTableName], [imtTransactionType], [imtSource], [imtNonInventoryTransaction], [imtJobID], [imtJobAssemblyID], [imtJobMaterialID], [imtPartID]) VALUES (117727, N'MaterialIssueLines', 2, 3, 0, N'23532-02-01', 0, 21, N'26271/2GC')
GO
INSERT [dbo].[PartTransactions] ([imtPartTransactionID], [imtTableName], [imtTransactionType], [imtSource], [imtNonInventoryTransaction], [imtJobID], [imtJobAssemblyID], [imtJobMaterialID], [imtPartID]) VALUES (117513, N'MfgReceipts', 1, 2, 1, N'23532-02-01', 0, 21, N'26271/2GC')
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117718, 1, 1, CAST(555.00000 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117718, 2, 2, CAST(555.00000 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117718, 3, 3, CAST(555.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117718, 4, 4, CAST(555.00000 AS Numeric(15, 5)), CAST(1.24865 AS Numeric(15, 5)), CAST(1.24865 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117719, 1, 1, CAST(555.00000 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117719, 2, 2, CAST(555.00000 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117719, 3, 3, CAST(555.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117719, 4, 4, CAST(555.00000 AS Numeric(15, 5)), CAST(1.16410 AS Numeric(15, 5)), CAST(1.16410 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117726, 1, 1, CAST(1100.00000 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117726, 2, 2, CAST(1100.00000 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117726, 3, 3, CAST(1100.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117726, 4, 4, CAST(1100.00000 AS Numeric(15, 5)), CAST(1.16410 AS Numeric(15, 5)), CAST(1.16410 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117725, 1, 1, CAST(555.00000 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117725, 2, 2, CAST(555.00000 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117725, 3, 3, CAST(555.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117725, 4, 4, CAST(555.00000 AS Numeric(15, 5)), CAST(1.16410 AS Numeric(15, 5)), CAST(1.16410 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117727, 1, 1, CAST(10.00000 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117727, 2, 2, CAST(10.00000 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117727, 3, 3, CAST(10.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117727, 4, 4, CAST(10.00000 AS Numeric(15, 5)), CAST(1.16410 AS Numeric(15, 5)), CAST(1.16410 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117513, 1, 1, CAST(555.00000 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)), CAST(1.61513 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117513, 2, 2, CAST(555.00000 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)), CAST(1.53503 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117513, 3, 3, CAST(555.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)), CAST(0.00000 AS Numeric(15, 5)))
GO
INSERT [dbo].[PartTransactionCosts] ([intPartTransactionID], [intPartTransactionCostID], [intCostType], [intQuantity], [intUnitMaterialCost], [intActualUnitMaterialCost]) VALUES (117513, 4, 4, CAST(555.00000 AS Numeric(15, 5)), CAST(1.24865 AS Numeric(15, 5)), CAST(1.24865 AS Numeric(15, 5)))
GO

更新:这是做什么的。

首先,这是来自名为 M1 的 ERP 系统的数据库后端。它的表结构是不可变的。

将材料接收到库存或直接接收到工作是通过“零件交易”完成的。零件交易与 4 种可能的零件交易成本类型之一相结合:1) 平均成本 2) 最后成本(与所讨论的工作无关) 3) 标准成本 4) 实际成本(直接接收到工作中)。使用哪个是由公司范围内的会计政策设置确定的。

平均成本用于从库存发放到作业或从作业返回到库存(未使用)的交易。这是在每次交易时在应用程序代码 (VB) 中计算的。

不涉及库存的材料问题和退货通过各种收据直接接收到作业,例如从采购订单或制造收据(表格:ReceiptLines、MfgReceipt)以及许多其他可能的方法(例如 DMR、 RMI、检验、报废、装运、调整)。这些实体的足迹不同,并且存储在不同的表中。

很遗憾,应用程序代码无法通过收据 (PO) 或制造收据可靠地将“收到的”成本存储到作业中,因此 PartTransactionCost(类型 4,实际)中的数据无法按预期使用。通常它确实计算正确,但神秘的是有时它没有。这是一个错误。

因此,以与任何收据相同的成本从工作中退回材料的唯一可靠方法是从适用的收据记录中获取实际成本。 COALESCE 函数按优先顺序选择非空连接,在没有找到收据的情况下(即所有空结果),最后的成本是平均成本。

在给出的示例数据中,有一张收货 555 数量的物品 21,单位成本为 1.25,然后所有 555 都被退回(即未使用)。这是通过 MaterialIssue 交易完成的(其符号为正,尽管 MaterialIssues 的数量为负),导致净数量为 0,净成本为 0.00。

然后又进行了两次收货,总数量为 1100,但收货单位成本与第一次收货不同。然后又发生了两次退货交易,导致净发行数量再次为 0。但是,我继承的代码并未导致净成本为零,因为简单连接产生了 3 x 3 接收和退货交易的叉积,对于总和中有 9 个分量的虚假结果。所以净退货成本是错误的倍数。很长一段时间都没有注意到这个错误,因为这种交易序列很少见。

必须注意的是,在这个例子中,最后的成本恰好是正确的,但由于它们不能被依赖,我需要从收据记录(表:MfgReceipts)中获取实际收到的成本,而不是从收据中获取transaction. 其他收款类型也需要相同的技术,例如在 ReceiptLines 表中。但只能使用一个收据记录。在所提供的解决方案中,最后收据的实际成本仅返回一次,并用于退货交易以代替存储的“最后成本”——这导致净出库数量为零,净成本为零。

【问题讨论】:

花时间在此处发布minimal reproducible example。那些我们无法消费的大型数据集的图像对于这里的许多用户来说将是一个瞬间的“关闭”。不要将数据发布为图像,将其发布为文本;最好作为 DDL 和 DML 语句。 我正在研究如何做到这一点。 看起来你需要横向连接(T-SQL 中的OUTER APPLY)。但是您的查询太长而无法深入研究,请弄清楚它是否真的是您需要的并将其写为答案 DDL 和编辑中添加的示例数据。 @JosephShirk 你是什么意思?如果您指的是投票,它们是匿名的;我没有说投票是我的。 【参考方案1】:

解决方案的精髓:

-- solved by example of answer 1-1) at 
-- https://***.com/questions/9275132/real-life-example-when-to-use-outer-cross-apply-in-sql

SELECT *
    
FROM 
    (SELECT 
        MI.imtJobID JobID
        , MI.imtJobAssemblyID AssemblyID
        , MI.imtJobMaterialID MaterialID
        , MI.imtPartTransactionID
        , intQuantity

     FROM PartTransactions MI -- Material Issue
     INNER JOIN PartTransactionCosts
          ON imtPartTransactionID = intPartTransactionID
     WHERE imtSource=3 
     AND intCostType = 4 -- Average cost, last resort
    ) MI
OUTER APPLY
    (SELECT TOP 1
        imtJobID JobID
        , imtJobAssemblyID AssemblyID
        , imtJobMaterialID MaterialID
        , intActualUnitMaterialCost, imtPartTransactionID 
        , imtTableName, intCostType
        
     FROM PartTransactions PTI JOIN PartTransactionCosts PTCI
        on PTI.imtPartTransactionID=PTCI.intPartTransactionID
        
     WHERE imtTableName='MfgReceipts'
     AND intCostType = 4
     AND PTI.imtJobID=MI.JobID AND PTI.imtJobAssemblyID=MI.AssemblyID AND PTI.imtJobMaterialID=MI.MaterialID

     AND PTI.imtPartTransactionID < MI.imtPartTransactionID 
        -- most recent recieved cost prior to this issuance
         
     ORDER BY PTI.imtPartTransactionID DESC
    ) MR

order by MI.MaterialID, MI.imtPartTransactionID

并且其结果更容易可视化,因此:

完整实现如下所示:

; WITH 
 MaterialIssues as (
        SELECT 
        MI.imtJobID JobID
        , MI.imtJobAssemblyID AssemblyID
        , MI.imtJobMaterialID MaterialID
        , 
        /* abstraction for different job types & sources*/
            (
            COALESCE(
                MR.intActualUnitMaterialCost 
                , RL.intActualUnitMaterialCost 
                , intUnitMaterialCost
            ) 
            + intUnitLaborCost 
            + intUnitOverheadCost 
            + intUnitSubcontractCost 
            + intUnitDutyCost 
            + intUnitFreightCost 
            + intUnitMiscCost
        ) UnitCost 
        , intQuantity 
        Quantity
        , imtSource
        , imtJobType
        , imtNonInventoryTransaction
        , imtReceiptID
        , imtTableName
    FROM PartTransactions MI
    INNER JOIN PartTransactionCosts
        ON imtPartTransactionID = intPartTransactionID
    LEFT JOIN Warehouses
        ON imtPartWarehouseLocationID = imwWarehouseID

    OUTER APPLY /* get single, most recent receieved cost */
        (   
            SELECT TOP 1
            imtJobID JobID, imtJobAssemblyID AssemblyID, imtJobMaterialID MaterialID
            , imtPartTransactionID
            , intActualUnitMaterialCost
            
            FROM PartTransactionCosts   PTCI
            JOIN PartTransactions       PTI 
                on imtPartTransactionID=intPartTransactionID
            WHERE imtTableName='MfgReceipts'
            AND intCostType = 4

            AND PTI.imtJobID=MI.imtJobID
            AND PTI.imtJobAssemblyID=MI.imtJobAssemblyID
            AND PTI.imtJobMaterialID=MI.imtJobMaterialID
            
            AND PTI.imtPartTransactionID < MI.imtPartTransactionID
            ORDER BY PTI.imtPartTransactionID DESC
        ) MR

    OUTER APPLY 
        (
            SELECT TOP 1
            imtJobID JobID, imtJobAssemblyID AssemblyID, imtJobMaterialID MaterialID
            , imtPartTransactionID
            , intActualUnitMaterialCost
            
            FROM PartTransactionCosts   PTCI
            JOIN PartTransactions       PTI 
                on imtPartTransactionID=intPartTransactionID
            WHERE imtTableName='ReceiptLines'
            AND intCostType = 4

            AND PTI.imtJobID=MI.imtJobID
            AND PTI.imtJobAssemblyID=MI.imtJobAssemblyID
            AND PTI.imtJobMaterialID=MI.imtJobMaterialID
            
            AND PTI.imtPartTransactionID < MI.imtPartTransactionID 
            ORDER BY PTI.imtPartTransactionID DESC
        ) RL

    WHERE 
            imtTransactionDate < @dEndDate
        AND imtTransactionDate >= @dStartDate
        AND (
            imtNonNettable = 0
            OR (
                imtNonNettable <> 0
                AND ISNULL(imwDoNotIncludeInJobCosts, 0) = 0
                )
            )
        AND intCostType = @nCostingMethod
                /* always 1 */
    
)
, PartTransactionMaterialCosts as (
    SELECT JobID, AssemblyID
        , SUM( 
                UnitCost
                * 
                (
                    (
                        CASE 
                            WHEN imtSource = 3
                            /*MaterialIssueLines*/
                                THEN - 1
                            ELSE 1
                            END
                    ) * Quantity
                )
            ) 
        NetCost /*NOTE: negated conditionally on Source 3*/
    FROM    MaterialIssues
    WHERE
            imtNonInventoryTransaction <= @bShowNonInventory
        AND imtSource   IN(2, 3)
        AND imtJobType  IN(1, 3)
        
        AND imtReceiptID = ''
        AND Upper(imtTableName) NOT IN ('RECEIPTLINES', 'MFGRECEIPTS', 'MFGRECEIPTCOMPONENTS', 'RECEIPTCOMPONENTS')

    GROUP BY JobID, AssemblyID
)
-- test:
Select * from PartTransactionMaterialCosts

【讨论】:

感谢@astentx 为我指明了正确的方向!

以上是关于外部引用来限制内部组的主要内容,如果未能解决你的问题,请参考以下文章

5.2访问限制

修复“xml外部实体引用的不当限制”的最佳方法是啥?

腾讯云设置安全组

面向对象编程——访问限制

python中访问限制

Python 面向对象编程——访问限制