我有以下查询。它使用三个子查询并且经常执行,所以我想将查询重写为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
答案 0 :(得分:2)
重写的问题是每个连接表中给定产品可能有很多行,总结果集将是Cartesian product;它将包含与每个连接表中匹配行数相乘的行数。
您可以确保每个联接表每个产品最多只有一行:
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;
此解决方案在技术上仍然使用子查询,但派生表子查询通常比您使用的相关子查询便宜。与往常一样,您只能通过测试确定它将如何影响您的数据。