数据集之间的SQL Server最佳日期匹配

时间:2017-08-26 14:40:16

标签: sql sql-server tsql

我需要使用@firstParty中的最佳匹配填充@thirdParty

要匹配的记录,@firstParty.Registered必须在@thirdParty.Registered的31天内。

此外,@thirdParty中的任何记录都无法与@firstParty中的多条记录相关联。

我想尽可能高效地完成这项工作。 SQL Server版本是2008,因此之后引入的功能无法使用。

此示例代码是实际代码的简化,我无法发布:

declare @firstParty table
(
    FirstPartyId integer identity,
    Registered date,

    MinThirdPartyId integer,
    MinThirdPartyRegistered date

);

insert into @firstParty (Registered)
values
('1/1/2017'), ('2/1/2017'), ('3/1/2017'), ('4/1/2017'), ('5/1/2017'), ('6/1/2017');

/*
dates in @firstParty and @thirdParty are not guaranteed to be unique 
in all scenarios
*/

declare @thirdParty table
(
    ThirdPartyId integer identity,
    Registered date
);

insert into @thirdParty (Registered)
values
('03/02/2017'), ('04/30/2017');


declare @x integer = 1;
while @x <= (select max(FirstPartyId) from @firstParty) begin

    declare @MinRegistered date = null;

    --get minimum third party date within 31 days of registered date, that hasn't been used
    select
        @MinRegistered = min(tp.Registered)     
    from
        @firstParty fp
        join @thirdParty tp on
            fp.Registered between dateadd(d, -31, tp.Registered) and dateadd(d, 31, tp.Registered)
        left join @firstParty used on tp.ThirdPartyId = used.MinThirdPartyId
    where
        fp.FirstPartyId = @x
        and used.MinThirdPartyId is null;

    declare @MinThirdPartyId integer = null;

    --get earliest ID of third party record with @MinRegistered
    select top 1
        @MinThirdPartyId = tp.ThirdPartyId
    from
        @firstParty fp
        join @thirdParty tp on
            tp.Registered = @MinRegistered
        left join @firstParty used on tp.ThirdPartyId = used.MinThirdPartyId
    where
        fp.FirstPartyId = @x
        and used.MinThirdPartyId is null
    order by
        tp.Registered,
        tp.ThirdPartyId;


    update @firstParty
    set
        MinThirdPartyId = @MinThirdPartyId,
        MinThirdPartyRegistered = @MinRegistered
    where
        FirstPartyId = @x;


    set @x = @x + 1;

end;


select
    fp.FirstPartyId,
    fp.Registered,
    fp.MinThirdPartyId,
    fp.MinThirdPartyRegistered
from
    @firstParty fp;

以下是我想要的结果:

FirstPartyId Registered MinThirdPartyId MinThirdPartyRegistered
------------ ---------- --------------- -----------------------
1            2017-01-01 NULL            NULL
2            2017-02-01 NULL            NULL
3            2017-03-01 1               2017-03-02
4            2017-04-01 NULL            NULL
5            2017-05-01 2               2017-04-30
6            2017-06-01 NULL            NULL

首先填充所有匹配然后删除非最佳匹配的方法将不起作用,因为如果删除@ firstParty的最佳@ thirdParty记录,则@thirdParty中可能存在仍然是可接受匹配的不同记录。

1 个答案:

答案 0 :(得分:1)

也许是这样的?

示例

Select A.FirstPartyId
      ,A.Registered
      ,MinThirdPartyId = B.ThirdPartyId
      ,MinThirdPartyRegistered = B.Registered
 From  @firstParty A
 Left  Join (
                Select B1.*
                      ,MinPartyID =B2.FirstPartyID
                 From  @thirdParty B1
                 Cross Apply (
                                Select Top 1 with ties *
                                 From @firstParty
                                 Where abs(DateDiff(DAY,B1.Registered,Registered))<=31
                                 Order By abs(DateDiff(DAY,B1.Registered,Registered)) 
                             ) B2
            ) B
  on (B.MinPartyID=A.FirstPartyId)

<强>返回

enter image description here