我有两张表Dispense& Pro Table,我想从分配表中选择所有行,从Pro表中选择最近的发货日期。
分配表
ID Dispense date Row ID
604743 10/18/2016 1
604743 11/4/2016 2
604743 11/28/2016 3
604743 12/16/2016 4
专业表
ID Shipment Date Row ID
604743 11/1/2016 1
604743 11/19/2016 2
604743 11/21/2016 3
604743 11/28/2016 4
604743 12/13/2016 5
需要输出
ID Dispense date Pre Ship date
604743 10/18/2016 NULL
604743 11/4/2016 11/1/2016
604743 11/28/2016 11/19/2016
604743 12/16/2016 12/13/2016
NULL
的原因:因为少于10/18的分发日期在Pro Table中的发货日期没有最近的日期
答案 0 :(得分:0)
我尝试了递归CTE,但他们并不是都在子查询中使用锚点。 因此,循环是我能做的最好的。
该脚本允许在同一日期使用多个Dispense或Pro,如果约束不允许,请参阅哪些部分可以抛出的注释。
--- Dispense_Date must not be unique
declare @Dispense table(
ID int not null,
Dispense_Date date not null,
Row_ID int not null identity primary key
)
-- Shipment_Date must not be unique
declare @Pro table(
ID int not null,
Shipment_Date date not null,
Row_ID int not null identity primary key
)
declare @Result table(
ID int not null,
Dispense_Date date not null,
Dispense_Row_ID int not null unique,
Shipment_Date date not null,
Pro_Row_ID int not null unique,
dayDiff int not null,
Row_ID int not null identity primary key,
iter int not null
)
insert into @Dispense(ID, Dispense_Date)
values (604743, '10/18/2016'),
(604743, '11/4/2016'),
/* (604743, '11/26/2016'),
(604743, '11/27/2016'),
(604743, '11/27/2016'),
(604743, '11/28/2016'), */
(604743, '11/28/2016'),
(604743, '12/16/2016')
insert into @Pro(ID, Shipment_Date)
values (604743, '11/1/2016'),
/* (604743, '11/16/2016'),
(604743, '11/19/2016'), */
(604743, '11/19/2016'),
(604743, '11/21/2016'),
(604743, '11/28/2016'),
(604743, '12/13/2016')
declare @iter int = 0
while exists(
select 1
from @Dispense Dispense
inner join
@Pro Pro
on Pro.ID = Dispense.ID
and
Pro.Shipment_Date < Dispense.Dispense_Date
where not exists(
select 1
from @Result Result
where Result.Dispense_Row_ID = Dispense.Row_ID
or
Result.Pro_Row_ID = Pro.Row_ID
)
)
begin
set @iter = @iter + 1
;
with distance(
ID, Dispense_Row_ID, Dispense_Date, Pro_Row_ID, Shipment_Date, dayDiff
) as(
select Dispense.ID,
Dispense.Row_ID Dispense_Row_ID,
Dispense.Dispense_Date,
Pro.Row_ID Pro_Row_ID,
Pro.Shipment_Date,
DATEDIFF(DAY, Pro.Shipment_Date, Dispense.Dispense_Date) dayDiff
from @Dispense Dispense
inner join
@Pro Pro
on Pro.ID = Dispense.ID
and
Pro.Shipment_Date < Dispense.Dispense_Date
where not exists(
select 1
from @Result Result
where Result.Dispense_Row_ID = Dispense.Row_ID
or
Result.Pro_Row_ID = Pro.Row_ID
)
)
insert into @Result(ID, Dispense_Row_ID, Dispense_Date, Pro_Row_ID, Shipment_Date, daydiff, iter)
select Dispense.ID,
Dispense.Row_ID Dispense_Row_ID,
Dispense.Dispense_Date,
distance.Pro_Row_ID,
distance.Shipment_Date,
distance.dayDiff,
@iter
from @Dispense Dispense
inner join
distance
on distance.Dispense_Row_ID = Dispense.Row_ID
and
not exists(
select 1
from distance dtExists
where dtExists.ID = distance.ID
and
dtExists.Shipment_Date = distance.Shipment_Date
and
(
dtExists.dayDiff < distance.dayDiff
-- below OR not needed if Dispense_Date and Shipment_Date are unique
or
(
dtExists.dayDiff = distance.dayDiff
and
(
dtExists.Pro_Row_ID < distance.Pro_Row_ID
or
(
dtExists.Pro_Row_ID = distance.Pro_Row_ID
and
dtExists.Dispense_Row_ID < distance.Dispense_Row_ID
)
)
)
)
)
and
not exists(
select 1
from distance dtExists
where dtExists.ID = distance.ID
and
dtExists.Dispense_Date = distance.Dispense_Date
and
(
dtExists.dayDiff < distance.dayDiff
-- below OR not needed if Dispense_Date and Shipment_Date are unique
or
(
dtExists.dayDiff = distance.dayDiff
and
(
dtExists.Pro_Row_ID < distance.Pro_Row_ID
or
(
dtExists.Pro_Row_ID = distance.Pro_Row_ID
and
dtExists.Dispense_Row_ID < distance.Dispense_Row_ID
)
)
)
)
)
end
select Dispense.ID,
Dispense.Row_ID Dispense_Row_ID,
Dispense.Dispense_Date,
Result.Pro_Row_ID,
Result.Shipment_Date,
Result.dayDiff,
Result.iter
from @Dispense Dispense
left join
@Result Result
on Result.Dispense_Row_ID = Dispense.Row_ID
order by Dispense.ID,
Dispense.Dispense_Date,
Result.Shipment_Date,
Result.Dispense_Row_ID,
Result.Pro_Row_ID