1

我有以下查询。它使用三个子查询并且经常执行,所以我想将查询重写为JOIN. 尽管我的值不正确,但我尝试这样做,有谁知道我如何成功地重写查询?

使用子查询进行查询

SELECT  PRODUCT.ID 
FROM    PRODUCT WHERE (
            COALESCE((SELECT SUM(AMOUNT) FROM CORRECTION WHERE CORRECTION.PRODUCT_ID = PRODUCT.ID),0)
            - COALESCE((SELECT SUM(AMOUNT) FROM ORDERROW WHERE ORDERROW.PRODUCTID = PRODUCT.ID),0)
            + COALESCE((SELECT SUM(AMOUNTOFPACKAGES * AMOUNTPERPACKAGE) FROM DELIVERYROW WHERE DELIVERYROW.PRODUCTID = PRODUCT.ID),0)
            ) > 0

带有连接的错误查询

SELECT  PRODUCT.ID
FROM    PRODUCT
LEFT JOIN CORRECTION  ON CORRECTION.PRODUCT_ID = PRODUCT.ID
LEFT JOIN ORDERROW    ON ORDERROW.PRODUCTID = PRODUCT.ID
LEFT JOIN DELIVERYROW ON DELIVERYROW.PRODUCTID = PRODUCT.ID
GROUP BY PRODUCT.ID
HAVING  (COALESCE(SUM(CORRECTION.AMOUNT),0)
        - COALESCE(SUM(ORDERROW.AMOUNT),0)
        + COALESCE(SUM(DELIVERYROW.AMOUNTOFPACKAGES * DELIVERYROW.AMOUNTPERPACKAGE),0) 
        ) > 0
4

1 回答 1

2

您重写的问题是,每个连接表中的给定产品可能有很多行,并且总结果集将是笛卡尔积;它的行数将与每个连接表中匹配的行数相乘。

您可以确保每个连接表每个产品最多有一行:

SELECT  PRODUCT.ID
FROM    PRODUCT
LEFT JOIN (SELECT PRODUCTID, SUM(AMOUNT) AS AMOUNT 
           FROM CORRECTION GROUP BY PRODUCTID) AS C
  ON C.PRODUCT_ID = PRODUCT.ID
LEFT JOIN (SELECT PRODUCTID, SUM(AMOUNT) AS AMOUNT 
           FROM ORDERROW GROUP BY PRODUCTID) AS O
  ON O.PRODUCTID = PRODUCT.ID
LEFT JOIN (SELECT PRODUCTID, SUM(AMOUNTOFPACKAGES * AMOUNTPERPACKAGE) AS AMOUNT 
           FROM DELIVERYROW GROUP BY PRODUCTID) AS D
  ON D.PRODUCTID = PRODUCT.ID
WHERE COALESCE(C.AMOUNT,0)
    - COALESCE(O.AMOUNT,0)
    + COALESCE(D.AMOUNT,0) > 0;

此解决方案在技术上仍然使用子查询,但派生表子查询通常比您使用的相关子查询便宜。与往常一样,您只能通过测试确定它将如何影响您的数据。

于 2013-07-17T18:03:57.573 回答