SQL Server中的SUM,在JOIN的一侧有多行,另一侧在另一侧作为比较

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL Server中的SUM,在JOIN的一侧有多行,另一侧在另一侧作为比较相关的知识,希望对你有一定的参考价值。

我有一个我试图找出的情况。我试图在大小级别上比较关于数量的两组数据。这似乎很简单,但问题是在某些情况下,数量可以在等式的一侧分成两行,因此我将有两行250与一行500相比。它们总数相等但是查询我写作似乎不起作用。我已经在下面发布了一些输出的查询。在第一个结果中,材料D68154尺寸L在查询的“M”侧有两条线,共计500条,查询“A”侧有一条线共500条。在我的理想情况下,这个结果不会像我一样回来不要只比较总和实际上不同的地方。有任何想法吗?谢谢。

查询:

SELECT
    M.STOCK_NUMBER AS [PO_NUMBER],
    M.MATERIAL, 
    M.MATERIAL_DESCRIPTION, 
    M.SIZE_LITERAL,
    A.GRID_VALUE,
    SUM(M.QUANTITY) AS [PO_QTY],
    SUM(A.QUANTITY) AS [SO_QTY],
    M.SALES_ORDER_NUMBER, 
    M.SALES_ORDER_ITEM_NUMBER, 
    M.CUSTOMER_NAME, 
    M.PLANNED_RECEIPT_DATE AS [ETA],
    M.PLANT_CODE

FROM VW_MRP_ALLOCATION M
JOIN VW_ARUN_NORM_NEW A   
    ON M.SALES_ORDER_NUMBER = A.SALES_ORDER_NUMBER AND
       M.SALES_ORDER_ITEM_NUMBER = A.SALES_ORDER_ITEM_NUMBER AND
       M.STOCK_NUMBER = A.SAP_PO_NUMBER AND
       M.SIZE_LITERAL = A.GRID_VALUE AND

       M.MATERIAL = A.MATERIAL_NUMBER
WHERE
    M.REQUIREMENT_TYPE = 'KE' AND
    M.STOCK_TYPE NOT IN ('A','C') AND
    M.STOCK_NUMBER IS NOT NULL 
GROUP BY
    M.STOCK_NUMBER,
    M.MATERIAL, 
    M.MATERIAL_DESCRIPTION, 
    M.SIZE_LITERAL, 
    M.SALES_ORDER_NUMBER, 
    M.SALES_ORDER_ITEM_NUMBER, 
    M.CUSTOMER_NAME, 
    M.PLANNED_RECEIPT_DATE,
    M.PLANT_CODE, 
    A.GRID_VALUE
HAVING

    SUM(M.QUANTITY) <> SUM(A.QUANTITY)

ORDER BY
    M.STOCK_NUMBER,
    M.SIZE_LITERAL;

结果:

PO_NUMBER    MATERIAL           MATERIAL_DESCRIPTION                     SIZE_LITERAL GRID_VALUE PO_QTY                                  SO_QTY                                  SALES_ORDER_NUMBER SALES_ORDER_ITEM_NUMBER                 CUSTOMER_NAME                       ETA                     PLANT_CODE
------------ ------------------ ---------------------------------------- ------------ ---------- --------------------------------------- --------------------------------------- ------------------ --------------------------------------- ----------------------------------- ----------------------- ----------
0283127530   D68154             GRAPHIC BRA         BLACK/WHITE          L            L          250                                     500                                     6194098835         10                                      ROSS STORES INC                     2018-03-31 00:00:00.000 6010
0283127530   D68154             GRAPHIC BRA         BLACK/WHITE          L            L          250                                     500                                     6194098835         10                                      ROSS STORES INC                     2018-04-28 00:00:00.000 6010
0283127530   D68154             GRAPHIC BRA         BLACK/WHITE          M            M          250                                     500                                     6194098835         10                                      ROSS STORES INC                     2018-03-31 00:00:00.000 6010
0283127530   D68154             GRAPHIC BRA         BLACK/WHITE          M            M          250                                     500                                     6194098835         10                                      ROSS STORES INC                     2018-04-28 00:00:00.000 6010
0283127560   D68153             BOLT TANK           DGSOGR               L            L          250                                     500                                     6194098839         10                                      ROSS STORES INC                     2018-03-31 00:00:00.000 6010
0283127560   D68153             BOLT TANK           DGSOGR               L            L          250                                     500                                     6194098839         10                                      ROSS STORES INC                     2018-04-28 00:00:00.000 6010
答案

尝试使用VW_ARUN_NORM_NEW的子查询。作为变种

SELECT
    ...    
FROM VW_MRP_ALLOCATION M
JOIN
  (
    SELECT
      SALES_ORDER_NUMBER,
      SALES_ORDER_ITEM_NUMBER,
      SAP_PO_NUMBER,
      GRID_VALUE,
      MATERIAL_NUMBER,
      SUM(QUANTITY) QUANTITY
    FROM VW_ARUN_NORM_NEW
    GROUP BY SALES_ORDER_NUMBER,SALES_ORDER_ITEM_NUMBER,SAP_PO_NUMBER,GRID_VALUE,
      MATERIAL_NUMBER
  ) A   
    ON M.SALES_ORDER_NUMBER = A.SALES_ORDER_NUMBER AND
       M.SALES_ORDER_ITEM_NUMBER = A.SALES_ORDER_ITEM_NUMBER AND
       M.STOCK_NUMBER = A.SAP_PO_NUMBER AND
       M.SIZE_LITERAL = A.GRID_VALUE AND
       M.MATERIAL = A.MATERIAL_NUMBER
WHERE
    M.REQUIREMENT_TYPE = 'KE' AND
    M.STOCK_TYPE NOT IN ('A','C') AND
    M.STOCK_NUMBER IS NOT NULL 
GROUP BY
    M.STOCK_NUMBER,
    M.MATERIAL, 
    M.MATERIAL_DESCRIPTION, 
    M.SIZE_LITERAL, 
    M.SALES_ORDER_NUMBER, 
    M.SALES_ORDER_ITEM_NUMBER, 
    M.CUSTOMER_NAME, 
    M.PLANNED_RECEIPT_DATE,
    M.PLANT_CODE, 
    A.GRID_VALUE
HAVING
    SUM(M.QUANTITY) <> SUM(A.QUANTITY)
ORDER BY
    M.STOCK_NUMBER,
    M.SIZE_LITERAL;

作为变体,您可以在查询中使用DISTINCT,但我认为这不是一个好方法。

尝试再检查一个变体

SELECT
    M.STOCK_NUMBER AS [PO_NUMBER],
    M.MATERIAL, 
    M.MATERIAL_DESCRIPTION, 
    M.SIZE_LITERAL,
    A.GRID_VALUE,
    SUM(M.QUANTITY) [PO_QTY],
    SUM(A.QUANTITY) AS [SO_QTY],
    M.SALES_ORDER_NUMBER, 
    M.SALES_ORDER_ITEM_NUMBER, 
    M.CUSTOMER_NAME, 
    M.PLANNED_RECEIPT_DATE AS [ETA],
    M.PLANT_CODE,
    M.STOCK_TYPE
FROM
  (
    SELECT
      STOCK_NUMBER,MATERIAL,MATERIAL_DESCRIPTION,SIZE_LITERAL,SALES_ORDER_NUMBER,SALES_ORDER_ITEM_NUMBER,CUSTOMER_NAME,PLANNED_RECEIPT_DATE,PLANT_CODE,STOCK_TYPE,
      QUANTITY,
      SUM(QUANTITY) OVER(PARTITION BY STOCK_NUMBER,MATERIAL,SALES_ORDER_NUMBER,SALES_ORDER_ITEM_NUMBER,SIZE_LITERAL) SUM_QUANTITY
    FROM VW_MRP_ALLOCATION
    WHERE REQUIREMENT_TYPE = 'KE' AND
        STOCK_TYPE NOT IN ('A','C') AND
        STOCK_NUMBER IS NOT NULL
  ) M
JOIN
  (
    SELECT
      SALES_ORDER_NUMBER,SALES_ORDER_ITEM_NUMBER,MATERIAL_NUMBER,GRID_VALUE,SAP_PO_NUMBER,
      QUANTITY,
      SUM(QUANTITY) OVER(PARTITION BY SALES_ORDER_NUMBER,SALES_ORDER_ITEM_NUMBER,MATERIAL_NUMBER,GRID_VALUE,SAP_PO_NUMBER) SUM_QUANTITY
    FROM VW_ARUN_NORM_NEW
    WHERE STOCK_TYPE IN ('L','B')
  ) A
ON M.SALES_ORDER_NUMBER = A.SALES_ORDER_NUMBER AND
    M.SALES_ORDER_ITEM_NUMBER = A.SALES_ORDER_ITEM_NUMBER AND
    M.STOCK_NUMBER = A.SAP_PO_NUMBER AND
    M.SIZE_LITERAL = A.GRID_VALUE AND
    M.MATERIAL = A.MATERIAL_NUMBER

WHERE M.SUM_QUANTITY <> A.SUM_QUANTITY

GROUP BY M.STOCK_NUMBER,
    M.MATERIAL, 
    M.MATERIAL_DESCRIPTION, 
    M.SIZE_LITERAL,
    A.GRID_VALUE,
    M.SALES_ORDER_NUMBER, 
    M.SALES_ORDER_ITEM_NUMBER, 
    M.CUSTOMER_NAME, 
    M.PLANNED_RECEIPT_DATE,
    M.PLANT_CODE,
    M.STOCK_TYPE

ORDER BY
    M.STOCK_NUMBER,
    M.SIZE_LITERAL;
另一答案

好的,因此数据集中的差异比我原先想象的要多。以下解决方案似乎完美(到目前为止)。这很困难,因为我们的数据库是全球管理的,有时候改变潜行的最终用户没有意识到。这是一个查询的野兽,需要5分钟才能运行,但它返回到目前为止的正确结果 - 作为参考,我们有4种股票类型(A,B,C,L) - 目标是排除A和C - 我做了它是一种圆形的方式:

SELECT
    M.STOCK_NUMBER AS [PO_NUMBER],
    M.MATERIAL, 
    M.MATERIAL_DESCRIPTION, 
    M.SIZE_LITERAL,
    A.GRID_VALUE,
    M1.QUANTITY [PO_QTY],
    SUM(A.QUANTITY) AS [SO_QTY],
    M.SALES_ORDER_NUMBER, 
    M.SALES_ORDER_ITEM_NUMBER, 
    M.CUSTOMER_NAME, 
    M.PLANNED_RECEIPT_DATE AS [ETA],
    M.PLANT_CODE,
    M.STOCK_TYPE

FROM VW_MRP_ALLOCATION M
JOIN VW_ARUN_NORM_NEW A   
    ON M.SALES_ORDER_NUMBER = A.SALES_ORDER_NUMBER AND
       M.SALES_ORDER_ITEM_NUMBER = A.SALES_ORDER_ITEM_NUMBER AND
       M.STOCK_NUMBER = A.SAP_PO_NUMBER AND
       M.SIZE_LITERAL = A.GRID_VALUE AND
       M.MATERIAL = A.MATERIAL_NUMBER
JOIN   (SELECT M1.STOCK_NUMBER,M1.MATERIAL,M1.SALES_ORDER_NUMBER,M1.SALES_ORDER_ITEM_NUMBER,M1.SIZE_LITERAL,SUM(M1.QUANTITY) AS [QUANTITY] FROM VW_MRP_ALLOCATION M1 
        GROUP BY M1.STOCK_NUMBER,M1.MATERIAL,M1.SALES_ORDER_NUMBER,M1.SALES_ORDER_ITEM_NUMBER,M1.SIZE_LITERAL,M1.SALES_ORDER_ITEM_NUMBER) AS [M1]
ON     M.STOCK_NUMBER = M1.STOCK_NUMBER AND
       M.MATERIAL = M1.MATERIAL AND 
       M1.MATERIAL = A.MATERIAL_NUMBER AND
       M1.SIZE_LITERAL = A.GRID_VALUE AND 
       M1.SALES_ORDER_NUMBER = A.SALES_ORDER_NUMBER AND 
       M1.SALES_ORDER_ITEM_NUMBER = A.SALES_ORDER_ITEM_NUMBER
JOIN   (SELECT A1.SALES_ORDER_NUMBER,A1.SALES_ORDER_ITEM_NUMBER,A1.MATERIAL_NUMBER,A1.GRID_VALUE,A1.SAP_PO_NUMBER,SUM(A1.QUANTITY) AS [QUANTITY] FROM VW_ARUN_NORM_NEW A1
        WHERE STOCK_TYPE IN ('L','B')
        GROUP BY A1.SALES_ORDER_NUMBER,A1.SALES_ORDER_ITEM_NUMBER,A1.MATERIAL_NUMBER,A1.GRID_VALUE,A1.SAP_PO_NUMBER) AS [A1]
ON     A1.SALES_ORDER_NUMBER = M1.SALES_ORDER_NUMBER AND 
       A1.SALES_ORDER_ITEM_NUMBER = M1.SALES_ORDER_ITEM_NUMBER AND 
       A1.MATERIAL_NUMBER = M1.MATERIAL AND 
       A1.GRID_VALUE = M1.SIZE_LITERAL 

WHERE
    M.REQUIREMENT_TYPE = 'KE' AND
    M.STOCK_TYPE NOT IN ('A','C') AND
    M.STOCK_NUMBER IS NOT NULL

GROUP BY
    M.STOCK_NUMBER,
    M.MATERIAL, 
    M.MATERIAL_DESCRIPTION, 
    M.SIZE_LITERAL, 
    M.SALES_ORDER_NUMBER, 
    M.SALES_ORDER_ITEM_NUMBER, 
    M.CUSTOMER_NAME, 
    M.PLANNED_RECEIPT_DATE,
    M.PLANT_CODE, 
    A.GRID_VALUE,
    M.STOCK_TYPE,
    M1.QUANTITY,
    A1.QUANTITY

HAVING M1.QUANTITY <> A1.QUANTITY

ORDER BY
    M.STOCK_NUMBER,
    M.SIZE_LITERAL;

以上是关于SQL Server中的SUM,在JOIN的一侧有多行,另一侧在另一侧作为比较的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 中的复合 SUM [重复]

SQL Server 中的 LEFT JOIN 与 LEFT OUTER JOIN

SQL Server Join方式

SQL Server:仅使用一次 Join/Cross Apply 中的记录

ORACLE LEFT JOIN 子查询 在SQL SERVER中可以使用如图中的子查询,ORACLE中怎么实现

SQL Server NOLOCK 与 JOIN,批量加载