简体   繁体   English

从表 A 到表 B 返回值

[英]Return values from Table A to Table B

I need help.我需要帮助。 Hi guys, I have 2 tables and I want to return the FIRST DueDate and QtyReceive from Table A to Table B if RunningTotalQtyReceive (from Table A) >= RunningTotalQtyShort (from Table B).大家好,我有 2 个表,如果 RunningTotalQtyReceive(来自表 A)>= RunningTotalQtyShort(来自表 B),我想将表 A 中的FIRST DueDate 和 QtyReceive 返回到表 B。 It returns NULL if QtyReceive/TotalRunningQtyReceive can't cover QtyShort/TotalRunningQtyShort.如果 QtyReceive/TotalRunningQtyReceive 无法覆盖 QtyShort/TotalRunningQtyShort,则返回 NULL。 The dataset has been ordered by Date.数据集已按日期排序。 RunningTotalQtyReceive and RunningTotalQtyShort have been calculated by Window Function. RunningTotalQtyReceiveRunningTotalQtyShort由 Window Function 计算得出。

SUM(QtyReceive) OVER(PARTITION BY Item ORDER BY DueDate)
SUM(QtyShort) OVER(PARTITION BY Item ORDER BY MatlDueDate)

Table A:表 A:

Item     DueDate         QtyReceive   RunningTotalQtyReceive
 A1     2021-10-08            6                6
 A1     2021-10-22            5                11
 A1     2022-02-01            9                20

Table B:表 B:

Item    MatlDueDate     QtyShort    RunningTotalQtyShort
 A1      2022-06-01        0                0
 A1      2022-06-03        1                1
 A1      2022-06-04        2                3
 A1      2022-06-05        4                7
 A1      2022-06-06        8                15
 A1      2022-06-07        5                20
 A1      2022-06-08        3                23
 A1      2022-06-09        10               33

Expected Output:预期 Output:

Item    MatlDueDate QtyShort    RunningTotalQtyShort    RunningTotalQtyReceive  DueDate    QtyReceive
 A1     2022-06-01     0                 0                       6             2021-10-08      6
 A1     2022-06-03     1                 1                       6             2021-10-08      6
 A1     2022-06-04     2                 3                       6             2021-10-08      6
 A1     2022-06-05     4                 7                       11            2021-10-22      5
 A1     2022-06-06     8                 15                      20            2022-02-01      9
 A1     2022-06-07     5                 20                      20            2022-02-01      9
 A1     2022-06-08     3                 23                      NULL            NULL          NULL
 A1     2022-06-09     10                33                      NULL              NULL        NULL

This is my script to return the expected output:这是我返回预期 output 的脚本:

SELECT 
     b.*, 
     c.RunningTotalQTyReceive, 
     c.DueDate, 
     c.QtyReceive
FROM TableB b 
OUTER APPLY (SELECT TOP 1 
                a.RunningTotalQTyReceive,
                FIRST_VALUE(DueDate) OVER(ORDER BY DueDate) AS DueDate, 
                a.QtyReceive
             FROM TableA a
             WHERE a.item = b.item
             AND a.RunningTotalQtyReceive >= b.RunningTotalQtyShort
             ) c

The problem is that this is "Triangular" Join ( https://www.sqlservercentral.com/articles/hidden-rbar-triangular-joins#:~:text=A%20Triangular%20Join%20is%20nothing,rows%20spawned%20are%20nearly%20trivial ) which slows down the query execution time.问题是这是“三角形”连接( https://www.sqlservercentral.com/articles/hidden-rbar-triangular-joins#:~:text=A%20Triangular%20Join%20is%20nothing,rows%20spawned% 20are%20nearly%20trivial ) 会减慢查询执行时间。 It took me 35 mins to 1 hour to finish the execution with the 200,000-row dataset.我用了 35 分钟到 1 小时完成了 200,000 行数据集的执行。 Could you please help me with any idea to reduce the time execution?你能帮我想办法减少执行时间吗? Any other joins or user-defined functions?任何其他联接或用户定义的函数? Thank you a lot.十分感谢。 Any help will be appreciated.任何帮助将不胜感激。 Please let me know if you need any clarification on my question.如果您需要对我的问题进行任何澄清,请告诉我。

Create TableA:创建表A:

CREATE TABLE TableA
(
Item varchar(2),
DueDate date,
QtyReceive int,
RunningTotalQtyReceive int
);

INSERT INTO TableA values
('A1',      '10/08/2021',       6,       6),
('A1',      '10/22/2021',       5,      11),
('A1',      '02/01/2022',       9,      20);

Create TableB:创建表B:

CREATE TABLE TableB
(
Item varchar(2),
MatlDueDate date,   
QtyShort int,
RunningTotalQtyShort int,
);

INSERT INTO TableB values
('A1',      '06/01/2022',         0,         0),
('A1',      '06/03/2022',         1,         1),
('A1',      '06/04/2022',         2,         3),
('A1',      '06/05/2022',         4,         7),
('A1',      '06/06/2022',         8,         15),
('A1',      '06/07/2022',         5,         20),
('A1',      '06/08/2022',         3,         23),
('A1',      '06/09/2022',         10,        33);

You don't need to store the values of RunningTotalQtyReceive and RunningTotalQtyShort, since they can be calculated from the input tables.您不需要存储 RunningTotalQtyReceive 和 RunningTotalQtyShort 的值,因为它们可以从输入表中计算出来。 Try the following to get the desired results:尝试以下操作以获得所需的结果:

With CTE1 AS
(
  Select Item, DueDate, QtyReceive,  
         SUM(QtyReceive) OVER(PARTITION BY Item ORDER BY DueDate) AS RunningTotalQtyReceive
  From TableA
),
CTE2 AS
(
 Select Item, MatlDueDate, QtyShort,
        SUM(QtyShort) OVER(PARTITION BY Item ORDER BY MatlDueDate) AS RunningTotalQtyShort
 From TableB
)

Select B.Item, B.MatlDueDate, B.QtyShort, B.RunningTotalQtyShort,
       A.RunningTotalQtyReceive, A.DueDate, A.QtyReceive
From CTE2 B
Left Join
(
  Select Item, DueDate, QtyReceive, RunningTotalQtyReceive, 
         LAG(RunningTotalQtyReceive, 1, 0) Over (Partition By Item Order By DueDate) AS lrtqr
  From CTE1
) A

On B.RunningTotalQtyShort <=  A.RunningTotalQtyReceive and B.RunningTotalQtyShort >=  A.lrtqr
And B.Item = A.Item

See a demo from db<>fiddle .查看db<>fiddle的演示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM