QUERY - 根据日期和过滤结果连接两个表

tma*_*lse 5 sql-server-2012

我为这个神秘的标题道歉。我想我无法将我的问题浓缩为一个标题,这表明我无法回答以下问题:

我有两个表(MS SQL Server 2012)中的数据。一张桌子producedpackaged

中的数据produced具有order number,product codestart date

产生

pr_order |   code  |   startdate
---------------------------------
8000009  |   pr_12 |   2016-05-23
8000002  |   pr_12 |   2016-04-01
8000001  |   pr_12 |   2016-03-29

8000010  |   pr_10 |   2016-05-26
8000008  |   pr_10 |   2016-05-01
etc.
Run Code Online (Sandbox Code Playgroud)

在数据packagedorder numberproduced product codepackaged product code和一个start date

包装好的

pa_order |  pr_code |   pa_code  |  startdate
----------------------------------------------
7000100  |  pr_12   |   pa_999   |  2016-05-26
7000102  |  pr_12   |   pa_888   |  2016-05-24
7000098  |  pr_12   |   pa_777   |  2016-04-01
7000088  |  pr_12   |   pa_999   |  2016-03-31
7000104  |  pr_12   |   pa_808   |  2016-03-30

7000105  |  pr_10   |   pa_101   |  2016-05-26
7000109  |  pr_10   |   pa_202   |  2016-05-26
7000099  |  pr_10   |   pa_107   |  2016-05-26
7000095  |  pr_10   |   pa_202   |  2016-05-03
7000094  |  pr_10   |   pa_107   |  2016-05-02
7000093  |  pr_10   |   pa_666   |  2016-05-01
etc.
Run Code Online (Sandbox Code Playgroud)

我正在尝试创建一个查询,显示produced订单号的packaged订单号。

以下适用:

  • packaged order pr_code == produced order code
  • packaged order startdate >= produced order startdate
  • a仅在以下packaged order情况下“链接”到 a produced order

    具有相同 的两个记录packaged order startdate之间的下降。produced order startdatesproduced order code

  • produced order 有一个或多个 packaged order(s)
  • packaged order 有一个 produced order

结果应如下所示:

pa_code |   pr_code |   pa_order |   pr_order
--------------------------------------------------
pa_999  |   pr_12   |   7000100  |   8000009
pa_999  |   pr_12   |   7000088  |   8000001
pa_888  |   pr_12   |   7000102  |   8000009
pa_808  |   pr_12   |   7000104  |   8000001
pa_777  |   pr_12   |   7000098  |   8000002
pa_202  |   pr_10   |   7000109  |   8000010
pa_202  |   pr_10   |   7000095  |   8000008
etc.
Run Code Online (Sandbox Code Playgroud)

基本上,考虑到生产和包装订单的开始日期,我正在尝试创建一个包装订单所属的生产订单概览。

我已经尝试过(很多变体)以下(在这里小提琴):

SELECT      p.pa_code
           ,p.pr_code
           ,p.pa_order
           ,r.pr_order
FROM        packaged p 
JOIN        produced r 
    ON      p.pr_code = r.code
    AND     p.startdate <= r.startdate
    AND     p.startdate >   (
                                SELECT  ISNULL(MAX(o.startdate),r.startdate)
                                FROM    produced o 
                                WHERE   o.code = p.pr_code
                                    AND o.startdate < r.startdate
                            )
ORDER BY    p.pa_order DESC;
Run Code Online (Sandbox Code Playgroud)

这导致(很多变化)这个:

pa_code | pr_code | pa_order |  pr_order
--------|---------|----------|----------
pa_202  | pr_10   | 7000109  |  8000010    correct
pa_101  | pr_10   | 7000105  |  8000010    correct
pa_808  | pr_12   | 7000104  |  8000002    wrong
pa_999  | pr_12   | 7000100  |  8000009    correct
pa_107  | pr_10   | 7000099  |  8000010    correct
pa_777  | pr_12   | 7000098  |  8000002    correct
pa_202  | pr_10   | 7000095  |  8000010    wrong
pa_107  | pr_10   | 7000094  |  8000010    wrong
pa_999  | pr_12   | 7000088  |  8000002    wrong

--and order 7000093 is missing...
Run Code Online (Sandbox Code Playgroud)

我只是不明白如何根据订单的开始日期将打包订单链接到生产订单。(仅当打包开始日期等于或大于相应的生产订单并且该打包订单的开始日期低于“下一个”(如果有)生产订单的开始日期时,打包订单才“链接”到生产订单。 (我希望这是有道理的...)

基于示例数据的正确结果应该是:

pa_code | pr_code | pa_order |  pr_order
--------|---------|----------|----------
pa_202  | pr_10   | 7000109  |  8000010    
pa_101  | pr_10   | 7000105  |  8000010    
pa_808  | pr_12   | 7000104  |  8000001    
pa_999  | pr_12   | 7000100  |  8000009    
pa_107  | pr_10   | 7000099  |  8000010    
pa_777  | pr_12   | 7000098  |  8000002    
pa_202  | pr_10   | 7000095  |  8000008    
pa_107  | pr_10   | 7000094  |  8000008  
pa_666  | pr_10   | 7000093  |  8000008      
pa_999  | pr_12   | 7000088  |  8000001    
Run Code Online (Sandbox Code Playgroud)

谁能帮助我了解如何获得正确的结果集?(抱歉问了这么长的问题!)

tma*_*lse 2

因此,经过大量的思考和反复试验(我必须承认大部分错误),我似乎偶然发现了我的问题的答案。

我做了以下事情:

  1. 创建一个临时表来保存结果,我们称之为result
  2. 填写result数据packaged
  3. 使用订单更新临时表produced

临时表:

CREATE TABLE #result
(  
     pa_order INT NOT NULL  
    ,pr_code NVARCHAR(5) NOT NULL  
    ,pa_code NVARCHAR(6) NOT NULL  
    ,startdate DATE NOT NULL  
    ,pr_order INT NULL  
);
Run Code Online (Sandbox Code Playgroud)

我使用这个查询(还没有小提琴,因为我不断收到网关超时)此处小提琴):

UPDATE  p
    SET p.pr_order =    
    (
        SELECT  MIN(r.pr_order) [pr_order]
        FROM    produced r
        WHERE   r.code = p.pr_code
            AND 
            ( 
                r.startdate >=  
                (
                    SELECT  ISNULL(MAX(r.startdate), p.startdate)
                    FROM    produced r
                    WHERE   r.code = p.pr_code
                    AND r.startdate <= p.startdate
                )
                AND
                r.startdate <=  
                (
                    SELECT  ISNULL(MAX(pr.startdate), r.startdate)
                    FROM    produced pr
                    WHERE   pr.code = p.pr_code
                    AND pr.startdate > r.startdate
                )
            )
    )
FROM    #result p;
Run Code Online (Sandbox Code Playgroud)

这会产生以下结果:

pa_code  | pr_code  | pa_order  |   pr_order
---------|----------|-----------|----------
pa_202   | pr_10    | 7000109   |   8000010
pa_101   | pr_10    | 7000105   |   8000010
pa_808   | pr_12    | 7000104   |   8000001
pa_888   | pr_12    | 7000102   |   8000009
pa_999   | pr_12    | 7000100   |   8000009
pa_107   | pr_10    | 7000099   |   8000010
pa_777   | pr_12    | 7000098   |   8000002
pa_202   | pr_10    | 7000095   |   8000008
pa_107   | pr_10    | 7000094   |   8000008
pa_666   | pr_10    | 7000093   |   8000008
pa_999   | pr_12    | 7000088   |   8000001
Run Code Online (Sandbox Code Playgroud)

这正是我所期望的。我不确定这是否是最优雅或“最好”的解决方案,但对我来说,它有效。