如何连接表以将一条记录分配给" FIFO"为了

时间:2015-12-16 10:22:37

标签: sql sql-server sql-server-2012

我尝试将一个表中的多个记录分配给第二个表中的单个记录,直到达到数量。我正在使用MS SQL 2012。

我们有这个外部发票表

ExtInvoice

+-------------+------+------+-------------+----------+----------+
| Ext_Invoice | P_No | Part | InvoiceDate | Due_Date | NumOrder |
+-------------+------+------+-------------+----------+----------+
|         571 |  607 | 7991 |      151116 |   151222 |        1 |
|         572 |  607 | 7991 |      151120 |   151228 |        2 |
|         573 |  607 | 7991 |      151127 |   160104 |        3 |
+-------------+------+------+-------------+----------+----------+

InternalInvoice

+------------+----------+------+------+-----+----------+
| Invoice_No | Original | P_No | Part | Qty | NumOrder |
+------------+----------+------+------+-----+----------+
|        198 | 607      |  607 | 7991 |   2 |        1 |
|        199 | RE607    |  607 | 7991 |   1 |        2 |
|        200 | RE607    |  607 | 7991 |   1 |        3 |
+------------+----------+------+------+-----+----------+

结果是将ExtInvoice中的前2个记录分配到InternalInvoice中的第一个记录,其余记录应转到第二个InternalInvoice记录。 ExtInvoice中的每一行代表一个Quantity

NumOrder不是唯一的,因为这是ROW_Number SQL计算。

所需的结果是:

enter image description here

表中显然有更多的发票,但这是它无法正常工作的部分。有一些带有row_number()操作的临时表来访问表ExtInvoice,InternalInvoice。我实际上使用了这个thread

我目前正在使用

 SELECT * 
 FROM InternalInvoice AS R      
 JOIN ExtInvoice AS S
   ON S.P_No=R.P_No
   AND S.Part=R.Part
   AND  R.Qty>=S.NumOrder

这就是我所得到的。我尝试了很多不同的方法,但看起来我现在被卡住了。任何帮助表示赞赏。

enter image description here

对不起图片链接,似乎我还没有直接链接图片的声誉。当我得到足够的代表时,我会改回来。

1 个答案:

答案 0 :(得分:1)

计算Qty的运行总和,以了解要使用

ExtInvoice跳过多少行
SUM(Qty) OVER (PARTITION BY P_No ORDER BY NumOrder)

使用OUTER APPLY连接表格并选择QtyTOP定义的行数。

示例数据

我又添加了一个P_No来验证结果是否已正确分区。

DECLARE @ExtInvoice TABLE 
(Ext_Invoice int, P_No int, Part int, InvoiceDate int, Due_Date int, NumOrder int);

INSERT INTO @ExtInvoice
(Ext_Invoice, P_No, Part, InvoiceDate, Due_Date, NumOrder)
VALUES
(571, 607, 7991, 151116, 151222, 1),
(572, 607, 7991, 151120, 151228, 2),
(573, 607, 7991, 151127, 160104, 3),
(574, 608, 7991, 151127, 160104, 1);


DECLARE @InternalInvoice TABLE
(Invoice_No int, Original varchar(5), P_No int, Part int, Qty int, NumOrder int);

INSERT INTO @InternalInvoice
(Invoice_No, Original, P_No, Part, Qty, NumOrder)
VALUES
(198, '607', 607, 7991, 2, 1),
(199, 'RE607', 607, 7991, 1, 2),
(200, 'RE607', 607, 7991, 1, 3),
(201, 'RE608', 608, 7991, 1, 1);

<强>查询

我是最终查询,您应该列出实际的列名而不是*。 为了使其有效工作,ExtInvoice上的(P_No, NumOrder)表应该有一个索引。

WITH
CTE_InternalInvoices
AS
(
    SELECT
        I.*
        ,SUM(Qty) OVER (PARTITION BY P_No ORDER BY NumOrder) AS SumQty
    FROM
        @InternalInvoice AS I
)
SELECT
    *
FROM
    CTE_InternalInvoices
    OUTER APPLY
    (
        SELECT TOP(CTE_InternalInvoices.Qty) *
        FROM @ExtInvoice AS E
        WHERE
            E.P_No = CTE_InternalInvoices.P_No
            AND E.NumOrder > CTE_InternalInvoices.SumQty - CTE_InternalInvoices.Qty
        ORDER BY E.NumOrder
    ) AS CA
ORDER BY CTE_InternalInvoices.Invoice_No;

<强>结果

+------------+----------+------+------+-----+----------+--------+-------------+------+------+-------------+----------+----------+
| Invoice_No | Original | P_No | Part | Qty | NumOrder | SumQty | Ext_Invoice | P_No | Part | InvoiceDate | Due_Date | NumOrder |
+------------+----------+------+------+-----+----------+--------+-------------+------+------+-------------+----------+----------+
|        198 | 607      |  607 | 7991 |   2 |        1 |      2 | 571         | 607  | 7991 | 151116      | 151222   | 1        |
|        198 | 607      |  607 | 7991 |   2 |        1 |      2 | 572         | 607  | 7991 | 151120      | 151228   | 2        |
|        199 | RE607    |  607 | 7991 |   1 |        2 |      3 | 573         | 607  | 7991 | 151127      | 160104   | 3        |
|        200 | RE607    |  607 | 7991 |   1 |        3 |      4 | NULL        | NULL | NULL | NULL        | NULL     | NULL     |
|        201 | RE608    |  608 | 7991 |   1 |        1 |      1 | 574         | 608  | 7991 | 151127      | 160104   | 1        |
+------------+----------+------+------+-----+----------+--------+-------------+------+------+-------------+----------+----------+

SQL Fiddle