【问题标题】:SQL OUTER JOIN column sum returning twice the amountSQL OUTER JOIN 列总和返回两倍的金额
【发布时间】:2015-01-13 19:11:34
【问题描述】:

我有一个显示查询,主要显示现有库存、订单库存和储备库存。除了一部分之外,一切都很好 - 重量和数量的总和返回了双倍的结果(仅在订购一定数量的情况下)。我确定我已经把我的连接塞满了,但我不知道怎么做。

当前输出(加倍总和):

PartNo                     Branch SOHWeight SOHQty ReservedQty SOOEa SOOTo AvgCost type product grade coating finish thickness width length dim1 dim2 Notes                                                                                                                                                                                                                                                            ClassFBR ClassFME ClassFSY AltoQty
-------------------------- ------ --------- ------ ----------- ----- ----- ------- ---- ------- ----- ------- ------ --------- ----- ------ ---- ---- -----
B-254-304---5--40-40-6000  FME    0.33      18     NULL        NULL  1.5   68.7494 B    ANGLE-E 304           NULL   5         NULL  6000   40   40   NULL                                                                                                                                                                                                                                                             C        A        B        NULL
Warning: Null value is eliminated by an aggregate or other SET operation.

预期输出完全一样,除了 SOHWeight 和 SOHQty 应该减半(与当前输出相比)

注意事项:

  • StockOnHand 将有许多具有相同 ProductDesc(部件号)的 PackNoID
  • 可以针对同一个 PackNoID 进行多次预订
SELECT dbo.tblProducts.PartNo,
       'FME'                                                                                                                                                                                                AS Branch,
       SUM(sOh.Weight)                                                                                                                                                                                      AS SOHWeight,
       SUM(sOh.Quantity)                                                                                                                                                                                    AS SOHQty,
       SUM(dbo.tblReserveDetail.Quantity)                                                                                                                                                                   AS ReservedQty,
       SUM(iif(dbo.tblPurchaseOrderDetail.QuantityUnit = 'TO', NULL, dbo.tblPurchaseOrderDetail.QuantityAmount))                                                                                            AS SOOEa,
       SUM(iif(dbo.tblPurchaseOrderDetail.QuantityUnit = 'TO', dbo.tblPurchaseOrderDetail.QuantityAmount, NULL))                                                                                            AS SOOTo,
       SUM(IIF(SoH.TYPE IN ( 'C', 'SC' ), SoH.COST * SoH.WEIGHT, SoH.COST * SoH.QUANTITY) + PROCESSINGCOST + PROCESSINGFREIGHT + Packaging) / SUM(IIF(SoH.TYPE IN ( 'C', 'SC' ), sOh.weight, sOh.Quantity)) AS AvgCost,
       tblProducts.type,
       tblProducts.product,
       tblProducts.grade,
       tblProducts.coating,
       tblProducts.finish,
       tblProducts.thickness,
       tblProducts.width,
       tblProducts.length,
       tblProducts.dim1,
       tblProducts.dim2,
       tblProducts.Notes,
       tblProducts.ClassFBR,
       tblProducts.ClassFME,
       tblProducts.ClassFSY,
       SUM(IIF(SoH.STATUS = 'SC', SoH.QUANTITY, NULL))                                                                                                                                                      AS AltoQty
FROM   DBO.tblProducts
       LEFT OUTER JOIN dbo.tblStockOnHand SoH
         ON tblProducts.PartNo = SOH.ProductDesc
            AND SoH.Status IN ( 'I', 'R', 'SC' )
            AND SoH.branch = 'FME'
       LEFT OUTER JOIN dbo.tblReserveDetail
                       RIGHT OUTER JOIN dbo.tblReserveHeader
                         ON dbo.tblReserveHeader.ID = dbo.tblReserveDetail.ReserveID
                            AND tblReserveHeader.Completed = 0
                            AND tblReserveHeader.Cancelled = 0
         ON SOH.PACKNOID = tblReserveDetail.PacknoID
       LEFT OUTER JOIN tblPurchaseOrderDetail
         ON dbo.tblPurchaseOrderDetail.ProductDesc = dbo.tblProducts.PartNo
            AND ( dbo.tblPurchaseOrderDetail.Status = N'O'
                   OR dbo.tblPurchaseOrderDetail.Status = N'PD' )
            AND tblPurchaseOrderDetail.branch = 'FME'
GROUP  BY dbo.tblProducts.PartNo,
          tblProducts.type,
          tblProducts.product,
          tblProducts.grade,
          tblProducts.coating,
          tblProducts.finish,
          tblProducts.thickness,
          tblProducts.width,
          tblProducts.length,
          tblProducts.dim1,
          tblProducts.dim2,
          tblProducts.Notes,
          tblProducts.ClassFBR,
          tblProducts.ClassFME,
          tblProducts.ClassFSY 

样本数据(精简): tblStockOnHand:

PackNoID    Status  Weight  Quantity    Cost    ProcessingCost  ProcessingFreight   Packaging   Branch  tblstockonhand.ProductDesc
157220  I   0.165   9   $68.47  $0.00   $2.48   $0.00   FME B-254-304---5--40-40-6000
158620  I   0.01839825  1   $64.27  $0.00   $4.72   $0.00   FSY B-254-304---5--40-40-6000

tblPurchaseOrderDetail

RecordId    Status  OrderNumber ItemNumber  QuantityAmount  QuantityUnit    PriceQuantity   PriceUnit   Branch  ProductDesc
6976    FD  4441    18  0.25    TO  3790    TO  FBR B-254-304---5--40-40-6000
6936    O   4439    23  0.5 TO  3790    TO  FME B-254-304---5--40-40-6000
6912    FD  4437    1   20  EA  75.96   EA  FSY B-254-304---5--40-40-6000

tblPurchaseOrderHeader

Status  OrderNumber Branch
O   4439    FME

tbl产品

PartNo  ClassFBR    ClassFME    ClassFSY    Notes   Type    Product Grade   Finish  Coating Thickness   Width   Length  Dim1    Dim2
B-254-304---5--40-40-6000   C   A   B       B   ANGLE-E 304         5       6000    40  40

【问题讨论】:

  • 请发布一些示例数据和预期结果
  • 编辑 OP 以显示样本数据和预期结果@Squirrel

标签: sql sql-server sum outer-join


【解决方案1】:

最后确定了,据我所知,我必须在 OUTER 加入它们之前对联接进行子查询,否则它们不会分组/求和,而是对返回的每条记录求和。我知道可怕的解释,但这是最终结果查询。感谢所有看过的人。

SELECT  dbo.tblProducts.PartNo, 'FME' AS Branch, SUM(sOh.Weight) AS SOHWeight, SUM(sOh.Quantity) AS SOHQty, 
        ReservedQty, SOOEa,SOOTo
        ,sum(IIF(SoH.TYPE IN ('C','SC'),SoH.COST*SoH.WEIGHT,SoH.COST*SoH.QUANTITY)+soh.PROCESSINGCOST+soh.PROCESSINGFREIGHT+soh.Packaging)/SUM(IIF(SoH.TYPE IN ('C','SC'),sOh.weight,sOh.Quantity)) AS AvgCost
        ,tblProducts.type,tblProducts.product,tblProducts.grade,tblProducts.coating,tblProducts.finish,tblProducts.thickness,tblProducts.width,tblProducts.length,tblProducts.dim1,tblProducts.dim2,tblProducts.Notes,tblProducts.ClassFBR,tblProducts.ClassFME,tblProducts.ClassFSY
        ,SUM(IIF(SoH.STATUS='SC',SoH.QUANTITY,NULL)) AS AltoQty
FROM 
        dbo.tblProducts 
        LEFT OUTER JOIN
        dbo.tblStockOnHand SoH  
        ON tblProducts.PartNo = SOH.ProductDesc AND SoH.Status IN ('I', 'R','SC') AND SoH.branch='FME' 
        LEFT OUTER JOIN
            (SELECT SUM(tblReserveDetail.Quantity) AS ReservedQty, ProductDesc
            FROM dbo.tblReserveDetail INNER JOIN tblReserveHeader ON dbo.tblReserveHeader.ID = dbo.tblReserveDetail.ReserveID INNER JOIN tblStockOnHand ON tblReserveDetail.PacknoID=tblStockOnHand.PackNoID
            WHERE tblReserveHeader.Completed=0 AND tblReserveHeader.Cancelled =0 AND BRANCH='FME'
            GROUP BY ProductDesc) RES
        ON SoH.ProductDesc = RES.ProductDesc 
        LEFT OUTER JOIN 
            (SELECT tblPurchaseOrderDetail.ProductDesc,SUM(iif(QuantityUnit='TO',null,QuantityAmount)) AS SOOEa,SUM(iif(QuantityUnit='TO',QuantityAmount,null)) AS SOOTo 
            FROM tblPurchaseOrderDetail WHERE
            (dbo.tblPurchaseOrderDetail.Status = N'O' OR dbo.tblPurchaseOrderDetail.Status = N'PD') AND tblPurchaseOrderDetail.branch='FME'
            GROUP BY tblPurchaseOrderDetail.ProductDesc) PoD
        ON PoD.ProductDesc = dbo.tblProducts.PartNo
GROUP BY dbo.tblProducts.PartNo,tblProducts.type,tblProducts.product,tblProducts.grade,tblProducts.coating,tblProducts.finish,tblProducts.thickness,tblProducts.width,tblProducts.length,tblProducts.dim1,tblProducts.dim2,tblProducts.Notes,tblProducts.ClassFBR,tblProducts.ClassFME,tblProducts.ClassFSY,SOOEa,SOOTo,ReservedQty

【讨论】:

    【解决方案2】:

    不看细节,右外连接是可疑的。右外连接总是可以被左外连接代替,两者一起使用很可能会产生混淆查询。这很可能是双重结果的原因。尝试重构,使所有连接都在外部而不是组合。

    【讨论】:

    • 试过了,不幸的是同样的结果。 :(
    • @JCro 我注意到在您下面的最终解决方案中,您也不再有右外连接。 :-)
    猜你喜欢
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 2015-09-10
    • 1970-01-01
    • 2018-10-14
    • 2023-03-26
    相关资源
    最近更新 更多