SQL乘以行.选择中彼此相邻的同一个表中的数据

Son*_*nia 5 sql t-sql sql-server multiplying matrix-multiplication

我有四个表:文档,项目,文章和文档关系.在文档中有三种类型的文档,这个问题只涉及其中两种:订单和发票.发票根据订单生成.发票可以有多个订单,一个订单可以有多个发票.订单和发票可以有多个项目.表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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

Articles: 
ID | Name
-- | ----
1  | A
2  | B
3  | c
Run Code Online (Sandbox Code Playgroud)

DocumentRelations:
OrderID | InvoiceID
------- | ---------
1       | 2
3       | 4
5       | 4
8       | 9
8       | 10
8       | 11
Run Code Online (Sandbox Code Playgroud)

场景1:发票/ s的相应订单/ s不存在.相应的发票/订单/ s不存在.

场景2:订单的相应发票/ s不包含与发票/ 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
Run Code Online (Sandbox Code Playgroud)

如果特定发票的订单不存在,则在名称和数量的列中保留为空.表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
Run Code Online (Sandbox Code Playgroud)

第二个类似于第一个但最后没有使用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
Run Code Online (Sandbox Code Playgroud)

xdd*_*xdd 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 
Run Code Online (Sandbox Code Playgroud)