如何合并两个日期最接近的两个表?

时间:2012-08-23 22:31:48

标签: sql sql-server sql-server-2008 tsql

我有两张表A和B,如下所示。我想按项目合并它们,但仅限于返回日期在订单日期之后的地方,并且返回日期最接近项目的相应订单日期。结果表格如下。你能帮忙看看我如何在SQL代码中实现这种合并吗?

退货日期不必与订单日期在同一年,但如果返回日期在订单日期之后,则应将其分配到最接近的订单日期。例如,对于项目1,在项目1的三个订单日期中,返回日期9/15/2009最接近8/14/2009,因此它被分配到8/14/2009。同样对于第1项,返回日期9/15/2011是在第1项的所有三个订单日期之后,但它最接近8/16/2011,因此它被分配到2011年8月16日。

非常感谢!

表A:

Items    Order_Date
1        8/14/2009
1        8/15/2010
1        8/16/2011
2        9/10/2009
2        9/8/2010
2        9/12/2011

表B:

Items    Return_Date
1        9/15/2009
1        9/15/2011
2        10/15/2010
2        11/15/2011

最终结果表C:

Items        Order_Date    Return_Date
1            8/14/2009     9/15/2009
1            8/15/2010     NULL
1            8/16/2011     9/15/2011
2            9/10/2009     NULL
2            9/8/2010      10/15/2010
2            9/12/2011     11/15/2011

3 个答案:

答案 0 :(得分:1)

我在这里也使用了APPLY。它似乎与您的示例数据匹配:

(答案结束时的样本数据)

;with MatchedOrders as (
    select
        a.Items,a.Order_Date, b.Return_Date 
    from
        @TableB b
            cross apply
        (select top 1 * from @TableA a
             where a.Items = b.Items and a.Order_Date < b.Return_Date
             order by a.Order_Date desc) a
)
select
    a.Items,
    a.Order_Date,
    mo.Return_Date
from
    @TableA a
        left join
    MatchedOrders mo
        on
            a.Items = mo.Items and a.Order_Date = mo.Order_Date

结果:

Items       Order_Date                  Return_Date
----------- --------------------------- ---------------------------
1           2009-08-14 00:00:00.0000000 2009-09-15 00:00:00.0000000
1           2010-08-15 00:00:00.0000000 NULL
1           2011-08-16 00:00:00.0000000 2011-09-15 00:00:00.0000000
2           2009-09-10 00:00:00.0000000 NULL
2           2010-09-08 00:00:00.0000000 2010-10-15 00:00:00.0000000
2           2011-09-12 00:00:00.0000000 2011-11-15 00:00:00.0000000

示例数据:

declare @TableA table (Items int not null,Order_Date datetime2 not null)
insert into @TableA(Items,Order_Date) values
(1,'20090814'),
(1,'20100815'),
(1,'20110816'),
(2,'20090910'),
(2,'20100908'),
(2,'20110912')

declare @TableB table (Items int not null,Return_Date datetime2 not null)
insert into @TableB(Items,Return_Date) values
(1,'20090915'),
(1,'20110915'),
(2,'20101015'),
(2,'20111115')

答案 1 :(得分:0)

我认为OUTER APPLY就是你所需要的。你尝试过这样的事情(SQLServer):

Select A.ItemID, A.OrderDate, [ReturnDates].ReturnDate
from Orders A
    OUTER APPLY (
        select Min(ReturnDate) as ReturnDate 
        From [Returns] b 
        where b.ReturnDate >= A.OrderDate AND b.ItemID = A.ItemID
        ) as ReturnDates

答案 2 :(得分:0)

试试这个:

select  ord.Items,ord.Order_Date,l.Return_Date  from orders ord
left join 
(
select * from (
select *,row_number() over (partition by return_date order by diff asc) as rn from (

select b.Items,b.Order_Date,a.Return_Date,a.diff  from 

(select o.Items,o.Order_Date,r.Return_Date,DATEDIFF(dd,o.Order_Date,r.Return_Date) diff  from orders o join ord_ret r
on o.Items = r.Items) a inner join 

(select a.Items,a.Order_Date,MIN(abs(a.diff)) as diff
from (
select o.Items,o.Order_Date,r.Return_Date,DATEDIFF(dd,o.Order_Date,r.Return_Date) diff  from orders o join ord_ret r
on o.Items = r.Items ) a
group by a.Items,a.Order_Date) b

on a.Items = b.Items and a.diff = b.diff  and a.Return_Date > b.Order_Date ) a) final
where rn<> 2) l

on ord.Items = l.Items and ord.Order_Date = l.Order_Date