如何在MySQL中达到3个表的FULL OUTER JOIN的结果

问题描述

基本上,我有四个表,每个表的字段如下:

customers:
customer_id,customer_name

products:
product_id,product_name

invoice:
id,invoice_number,customer_id

invoice_item:
id,invoice_id,product_id

我正在尝试实现:所有客户的客户名称以及所有产品的产品名称和NULL值(如果客户未购买特定产品)以及最终每个客户购买的产品数量。我知道MysqL中没有外部联接,因此我无法通过与每个联接进行外部联接购买并合并结果来做到这一点。现在我正在做的是:

SELECT * FROM (
SELECT * FROM
(select p.id as product_id,p.product_name,ii.invoice_id as invoice_id_1,ii.product_id as invoice_product_id
from products p
left join invoice_item ii on ii.product_id=p.id
union all
select null,null,ii.product_id,ii.invoice_id
from invoice_item ii
where not exists (select * from products p where p.id=ii.product_id)) as products
left join 
(select c.id as customer_id,c.customer_name,i.id as invoice_id_2,i.customer_id as invoice_customer_id
from customers c
left join invoice i on i.customer_id=c.id
union all
select null,i.id,i.customer_id
from invoice i
where not exists (select * from customers c where c.id=i.customer_id)) as customers
on customers.invoice_id_2 = products.invoice_id_1
union
SELECT * FROM
(select p.id as product_id,ii.invoice_id as invoice_id,ii.invoice_id
from invoice_item ii
where not exists (select * from products p where p.id=ii.product_id)) as products
right join 
(select c.id as customer_id,i.id as invoice_id,i.customer_id
from invoice i
where not exists (select * from customers c where c.id=i.customer_id)) as customers
on customers.invoice_id = products.invoice_id) AS T
left join 
(SELECT SUM(QUANTITY) AS QTY,PRODUCT_ID FROM INVOICE_ITEM
GROUP BY PRODUCT_ID) AS S
ON S.PRODUCT_ID = T.PRODUCT_ID
ORDER BY CUSTOMER_ID ASC,T.PRODUCT_ID ASC

这很丑。我想知道一种有效的方法来实现这一目标,或者在涉及到三个或更多表时通常可以有效地覆盖OUTER JOIN。

解决方法

我正在努力实现:所有客户的客户名称以及所有产品的产品名称和NULL值(如果客户未购买特定产品,最后是每个客户购买的产品数量)

我不知道您为什么需要java.lang.IllegalArgumentException at Test.main(Test.java:4) Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "s" is null at Test.main(Test.java:9) :据我了解您的问题,这是full join才能生成所有产品/客户组合,然后生成cross join-或相关子查询-带来总数。假设在left join中有一个名为qty的列:

invoice_item
,

您所获得的成果的丑陋版本:

SELECT 
    IFNULL(CUSTOMER_NAME,'N/A'),IFNULL(PRODUCT_NAME,IFNULL(QTY,0) 
FROM
(SELECT * FROM
(SELECT P.ID AS PRODUCT_ID_ORIG,P.PRODUCT_NAME,II.PRODUCT_ID,II.INVOICE_ID AS INVOICE_ITEM_INVOICE_ID,II.ID AS INVOICE_ITEM_ID
FROM PRODUCTS P LEFT JOIN INVOICE_ITEM II ON II.PRODUCT_ID = P.ID) PRODUCTS
LEFT JOIN 
(SELECT C.ID,C.CUSTOMER_NAME,I.ID AS INVOICE_ID FROM
CUSTOMERS C LEFT JOIN INVOICE I ON C.ID = I.ID) CUSTOMERS ON CUSTOMERS.INVOICE_ID = PRODUCTS.INVOICE_ITEM_INVOICE_ID
UNION
SELECT* FROM
(SELECT P.ID AS PRODUCT_ID_ORIG,II.ID AS INVOICE_ITEM_ID
FROM PRODUCTS P LEFT JOIN INVOICE_ITEM II ON II.PRODUCT_ID = P.ID) PRODUCTS
RIGHT JOIN 
(SELECT C.ID,I.ID AS INVOICE_ID FROM
CUSTOMERS C LEFT JOIN INVOICE I ON C.ID = I.ID) CUSTOMERS ON CUSTOMERS.INVOICE_ID = PRODUCTS.INVOICE_ITEM_INVOICE_ID)
AS T
LEFT JOIN 
(SELECT SUM(QUANTITY) AS QTY,PRODUCT_ID,INVOICE_ID FROM INVOICE_ITEM
GROUP BY PRODUCT_ID,INVOICE_ID) AS S
ON S.PRODUCT_ID = T.PRODUCT_ID_ORIG AND S.INVOICE_ID =T.INVOICE_ITEM_INVOICE_ID
ORDER BY ID ASC,T.PRODUCT_ID_ORIG ASC,T.INVOICE_ITEM_ID ASC