我有四个表:Documents,Items,Articles和DocumentRelations。在文档中有三种类型的文档,这个问题只涉及其中两种:订单和发票。发票根据订单生成。发票可以有多个订单,一个订单可以有多个发票。订单和发票可以有多个项目。表DocumentRelations包含订单和发票之间的关系,哪个发票是从哪个订单/订单生成的。
Documents:
ID | Name
-- | --------
1 | O/2017/1
2 | I/2017/1
3 | O/2017/2
4 | I/2017/2
5 | O/2017/3
6 | O/2017/4
.. | ...
99 | X/2017/1
Ttems:
ID | ArticleID | DocumentID | Quantity
-- | --------- | ---------- | --------
1 | 1 | 1 | 12
2 | 1 | 2 | 3
3 | 2 | 3 | 41
4 | 2 | 4 | 41
5 | 1 | 4 | 59
6 | 1 | 5 | 59
7 | 3 | 6 | 7
Articles:
ID | Name
-- | ----
1 | A
2 | B
3 | c
DocumentRelations:
OrderID | InvoiceID
------- | ---------
1 | 2
3 | 4
5 | 4
8 | 9
8 | 10
8 | 11
场景1:发票/ s的相应订单/ s不存在。相应的发票/订单/ s不存在。
场景2:订单的相应发票/ s不包含与发票/ s相同的每个项目的数量。发票的相应订单/ s不包含与订单/ s相同的每个项目数量。
我的问题开始了: 我需要以易于比较的形式获得每个文档中包含数量的项目列表。因此,订单的ID,发票的ID,项目的名称,订单中的数量,发票中的数量。
OrderID | InvoiceID | ItemNameInOrder | QuantityInOrder | QuantityInInvoice
------- | --------- | --------------- | --------------- | -----------------
1 | 2 | A | 12 | 3
3 | 4 | B | 41 | 41
5 | 4 | A | 59 | 59
6 | NULL | C | 7 | NULL
NULL | 7 | B | NULL | 11
8 | 9 | A | 10 | 9
8 | 10 | A | 10 | 9
8 | 11 | A | 10 | 19
如果特定发票的订单不存在,请在名称和数量的栏中留空。表DocumentRelations包含三种类型的文档,因此不应出现具有第三种文档的文档。
我的第一个计划是让两个选择仅返回我需要的列,每个列都用于文档类型。然后左边根据DocumentRelations中的ID加入它们。但这会使一切都成倍增加。比估计结果多3倍左右。
SELECT O.ID, I.ID, O.ArticleName, O.Quantity, I.Quantity
FROM DocumentRelations R
LEFT JOIN (SELECT D.ID, D.NumberString, I.Quantity, A.Name
FROM Documents D
JOIN Items I
ON D.ID = I.DocumentID
JOIN Articles A
ON I.ArticleID = A.ID
WHERE D.Name LIKE 'O/%') O
ON R.OrderID = O.ID
LEFT JOIN (SELECT D.ID, , I.Quantity, A.Name
FROM Documents D
JOIN Items I
ON D.ID = I.DocumentID
JOIN Articles A
ON I.ArticleID = A.ID
WHERE D.Name LIKE 'I/%') I
ON R.InvoiceID = I.ID
第二个类似于第一个,但最后没有使用DocumentRelations。创建两个选项,一个包含订单ID,项目名称,项目数量和相应发票的ID。第二个是相同的,但发票。基于具有相应文档ID的列加入全外连接,但结果是相同的。
SELECT O.ID, I.ID, O.ArticleName, O.Quantity, I.Quantity
FROM (SELECT D.ID, D.NumberString, I.Quantity, A.Name, R.InvoiceID
FROM Documents D
JOIN Items I
ON D.ID = I.DocumentID
JOIN Articles A
ON I.ArticleID = A.ID
LEFT JOIN DocumentRelations R
ON D.ID = R.OrderID
WHERE D.Name LIKE 'O/%') O
FULL OUTER JOIN (
SELECT D.ID, D.NumberString, I.Quantity, A.Name
FROM Documents D
JOIN Items I
ON D.ID = I.DocumentID
JOIN Articles A
ON I.ArticleID = A.ID
WHERE D.Name LIKE 'I/%') I
ON O.InvoiceID = I.ID
答案 0 :(得分:1)
我喜欢第二个 - 您只需要在条件中添加ArticleID即可 除了缺少某些字符串的名称外,你几乎可以得到你想要的东西。 我们假设您在一个文档中没有相同文章的两行或更多行:
SELECT O.ID, I.ID, O.ArticleName, O.Quantity, I.Quantity
FROM (SELECT D.ID, D.NumberString, I.Quantity, A.Name, R.InvoiceID, D.ArticleID
FROM Documents D
JOIN Items I
ON D.ID = I.DocumentID
JOIN Articles A
ON I.ArticleID = A.ID
LEFT JOIN DocumentRelations R
ON D.ID = R.OrderID
WHERE D.Name LIKE 'O/%') O
FULL OUTER JOIN (
SELECT D.ID, D.NumberString, I.Quantity, A.Name, D.ArticleID
FROM Documents D
JOIN Items I
ON D.ID = I.DocumentID
JOIN Articles A
ON I.ArticleID = A.ID
WHERE D.Name LIKE 'I/%') I
ON D.InvoiceID = I.ID
AND D.ArticleID = I.ArticleID