将SQL查询限制为一对一连接

时间:2017-07-12 00:58:35

标签: sql sql-server tsql

我在表格中有一个包含请求和响应的表。对于大多数记录,我们能够基于跟踪字段跟踪请求的响应。但是,由于请求发送给第三方,我们无法始终控制传入的响应,并且某些外部方不提供跟踪值。

现在,我有一个查询来查询记录并尝试在请求后3天内查找同一帐户的响应记录,因为响应可以在请求后的1-3天内到达。

此查询适用于99.9%的记录。但是,在某些情况下,会在同一天或一天​​后发出两个请求,并在1-2天后发出响应。在这些场景中,我在联接中有4条记录,因为2个请求中的每一个都加入到2个响应中的每一个,以产生4条记录。虽然我没有遇到过这种情况,但我确信3个请求可能会匹配3个响应,产生9个记录。

示例数据:

ID       | AccountNo   | TransReqDate | TransCompletedDate | TransType
3934023  | 0394212345  | 3/13/2017    | 3/13/2017          | Request
3934317  | 0394212345  | 3/14/2017    | 3/14/2017          | Request
3937450  | 0394212345  |              | 3/14/2017          | Response
3941189  | 0394212345  |              | 3/15/2017          | Response
3847921  | 0740112345  | 2/16/2017    | 2/16/2017          | Request
3848095  | 0740112345  | 2/16/2017    | 2/16/2017          | Request
3850082  | 0740112345  |              | 2/17/2017          | Response
3850084  | 0740112345  |              | 2/17/2017          | Response

查询:

select *
from MTPTransaction Request
    left join MTPTransaction  Response
        on Request.AccountNo=Response.AccountNo and
            Request.ID<Response.ID
            Response.TransCompletedDate > Request.TransCompletedDate and 
            Response.TransCompletedDate < dateadd(D,3,Request.TransCompletedDate)
where Request.TransType='Request' and Response.TransType='Response' 

预期结果:

ID       | AccountNo   | TransReqDate | TransCompletedDate | TransType
3934023  | 0394212345  | 3/13/2017    | 3/13/2017          | 3937450  | 0394212345  |             | 3/14/2017
3934317  | 0394212345  | 3/14/2017    | 3/14/2017          | 3941189  | 0394212345  |             | 3/15/2017
3847921  | 0740112345  | 2/16/2017    | 2/16/2017          | 3850082  | 0740112345  |             | 2/17/2017
3848095  | 0740112345  | 2/16/2017    | 2/16/2017          | 3850084  | 0740112345  |             | 2/17/2017

我的目标是将PK值最低的请求与具有最低PK值的响应匹配,并将具有最高PK值的请求与具有最高PK值的响应匹配。类似地,对于最低和最高PK值之间的任何记录,将1个请求与1个响应匹配。

非常感谢任何关于如何实现这一目标的建议。

由于

2 个答案:

答案 0 :(得分:1)

这个查询怎么样?

;WITH    RequestCTE
      AS ( SELECT   AccountNo ,
                    ID ,
                    TransReqDate ,
                    TransCompletedDate ,
                    ROW_NUMBER() OVER ( PARTITION BY AccountNo ORDER BY id ASC ) AS RN
           FROM     MTPTransaction request
           WHERE    TransType = 'Request'
         ),
    ResponseCTE
      AS ( SELECT   AccountNo ,
                    ID ,
                    TransReqDate ,
                    TransCompletedDate ,
                    ROW_NUMBER() OVER ( PARTITION BY AccountNo ORDER BY id ASC ) AS RN
           FROM     MTPTransaction request
           WHERE    TransType = 'Response'
         )
SELECT  *
FROM    RequestCTE req
        LEFT JOIN ResponseCTE res ON req.AccountNo = res.AccountNo
                                     AND req.RN = res.RN
                                     AND res.TransCompletedDate > req.TransCompletedDate
                                     AND res.TransCompletedDate < DATEADD(D,
                                                          3,
                                                          req.TransCompletedDate);

答案 1 :(得分:0)

与现有答案+1相似

(first.beginning_of_month..last).map { |d| d.strftime("%b %Y") if d.day == 1 }.compact
#=> ["Dec 2016", "Jan 2017", "Feb 2017", "Mar 2017"]