LEFT JOIN不考虑ON子句

时间:2015-04-21 10:02:49

标签: mysql sql

我的查询用于检索客户订购和退回的商品清单。我对上次加入ReturnCustomer感到困惑,我希望查询返回status = 20的数据,否则返回NULL。以下是我的询问:

SELECT Product.id AS product_id, Product.supplier_product_id AS vip_id, Product.name AS product_name, detailSO.qty, detailRC.return_qty
FROM Product
RIGHT JOIN detailSO ON detailSO.product_id = Product.id
RIGHT JOIN SalesOrder ON SalesOrder.id = detailSO.so_id AND SalesOrder.status >= 20
LEFT JOIN detailRC ON detailRC.sur_key = detailSO.sur_key
LEFT JOIN ReturnCustomer ON ReturnCustomer.id = detailRC.rc_id AND ReturnCustomer.status >= 20

如果我使用LEFT JOIN,则不会考虑ReturnCustomer.status >= 20,因为它会返回所有数据。另一方面,如果我使用RIGHT JOIN,则只返回ReturnCustomer.status >= 20

的数据

LEFT JOIN Result:

P_id    Pp_id   P_name  i_qty   r_qty
P000001 P000001 Item 1  15      1
P000001 P000001 Item 1  5       1
P000002 P000002 Item 2  5       NULL

RIGHT JOIN Result:

P_id    Pp_id   P_name  i_qty   r_qty
P000001 P000001 Item 1  15      1

Expected Result:

P_id    Pp_id   P_name  i_qty   r_qty
P000001 P000001 Item 1  15      1
P000001 P000001 Item 1  5       NULL <-- null since it comes from ReturnCustomer with status = 0
P000002 P000002 Item 2  5       NULL

我知道也许我可以使用嵌套查询解决这个问题,希望你们能为我提供更好的解决方案。提前致谢

更新 这是我的简化问题sqlfiddle ..

5 个答案:

答案 0 :(得分:2)

a LEFT JOIN b完全相同..(a将始终存在,其中b可能为空)

ON只能移除b,其中a不会受到影响。

WHERE可以删除行

所以当

 A have 1,2,3
 B have 1,2
 C have 1,3

当这三个人加入时,例如:

 SELECT *
 FROM A 
 LEFT JOIN B ON A.x = B.x
 LEFT JOIN C ON B.x = C.x

它会给:

 A B C
 1 1 1
 2 2
 3

如果第二个LEFT JOIN加入A,例如:

 SELECT *
 FROM A 
 LEFT JOIN B ON A.x = B.x
 LEFT JOIN C ON A.x = C.x

它会给:

 A B C
 1 1 1
 2 2
 3   3

上一个ON上的任何其他条件都不会删除B部分,因为它之前已加入,WHERE部分的任何条件都会删除整行。

在您的情况下,如果您要隐藏B部分,则不应使用ONWHERE,正确的部分将使用CASE WHEN { {1}}部分,例如:

SELECT

sql Fiddle的结果

SELECT detailSO.product_id
, detailSO.qty
, CASE WHEN RC.id IS NULL THEN NULL ELSE detailRC.qty END AS x
FROM SO
LEFT JOIN detailSO ON detailSO.so_id = SO.id
LEFT JOIN detailRC ON detailRC.sur_key = detailSO.sur_key
LEFT JOIN RC ON RC.id = detailRC.rc_id AND RC.status >= 20
WHERE SO.status >= 20

答案 1 :(得分:0)

这可能有效

SELECT 
  Product.id AS product_id,
  Product.supplier_product_id AS vip_id,
  Product.name AS product_name,
  detailSO.qty,
  detailRC.return_qty 
FROM
  Product 
  RIGHT JOIN detailSO 
    ON detailSO.product_id = Product.id 
  RIGHT JOIN SalesOrder 
    ON SalesOrder.id = detailSO.so_id 
    AND SalesOrder.status >= 20 
  LEFT JOIN detailRC 
    ON detailRC.sur_key = detailSO.sur_key 
  LEFT JOIN ReturnCustomer 
    ON ReturnCustomer.id = detailRC.rc_id 
    WHERE ReturnCustomer.status >= 20 

答案 2 :(得分:0)

你是否尝试过以下方法:

SELECT Product.id AS product_id, Product.supplier_product_id AS vip_id,   
       Product.name AS product_name, detailSO.qty, detailRC.return_qty
       FROM Product
       RIGHT JOIN detailSO ON detailSO.product_id = Product.id
       RIGHT JOIN SalesOrder ON SalesOrder.id = detailSO.so_id
       LEFT JOIN detailRC ON detailRC.sur_key = detailSO.sur_key
       LEFT JOIN ReturnCustomer ON ReturnCustomer.id = detailRC.rc_id 
where 
       ReturnCustomer.status >= 20
  AND  SalesOrder.status >= 20

答案 3 :(得分:0)

我怀疑这是评估NULL值的方式。尝试在ON子句中使用ISNULL:

SELECT Product.id AS product_id, Product.supplier_product_id AS vip_id, Product.name AS product_name, detailSO.qty, detailRC.return_qty
FROM Product
RIGHT JOIN detailSO ON detailSO.product_id = Product.id
RIGHT JOIN SalesOrder ON SalesOrder.id = detailSO.so_id AND SalesOrder.status >= 20
LEFT JOIN detailRC ON detailRC.sur_key = detailSO.sur_key
LEFT JOIN ReturnCustomer ON ReturnCustomer.id = detailRC.rc_id AND ISNULL(ReturnCustomer.status, 0) >= 20

答案 4 :(得分:0)

使用嵌套查询为您提供所需的结果

 SELECT temp.* from (
      SELECT 
      Product.id AS product_id,
      Product.supplier_product_id AS vip_id,
      Product.name AS product_name,
      detailSO.qty,
      detailRC.return_qty 
    FROM
      Product 
      RIGHT JOIN detailSO 
        ON detailSO.product_id = Product.id 
      RIGHT JOIN SalesOrder 
        ON SalesOrder.id = detailSO.so_id
      LEFT JOIN detailRC 
        ON detailRC.sur_key = detailSO.sur_key 
      LEFT JOIN ReturnCustomer 
        ON ReturnCustomer.id = detailRC.rc_id 

    ) as temp 
     WHERE temp .status >= 20