1

我正在寻找有关 SQL2016 的以下方面的帮助

我有批次需要识别父批次。

我需要填写的是 ParentBatchID 并且应该按照这个逻辑工作:

  1. 如果存在上一个批次,其中当前批次的起始日期介于上一个批次的起始日期和终止日期之间 -> 那就是父级
  2. 如果识别的parrent的parrentBatchID为0,则获取parrent的BatchID,如果不为0,则获取parrent的ParrentBatchID(继承)

到目前为止,我是用光标完成的,但性能是,你知道的,RBAR。*当当前 fromDate 介于前一个 from 和 to date+1 之间时,则 isnull(parrentBatchID,batchid) *

我尝试使用窗口函数,但是由于我需要继承的 parrentID 在下一行中还不存在,所以我失败了,到处都是 0-s :(

我对数据进行了自由操作,并尝试了各种准备方法。

Create table myTest (BatchID int, Product int, LenghtDay int, fromDate datetime, toDate Datetime, ParentBatchID int);

insert into myTest VALUES (1,1,9,'2000-01-01 00:00:00','2000-01-10 00:00:00',null);
insert into myTest VALUES (2,1,4,'2000-01-08 00:00:00','2000-01-12 00:00:00',null);
insert into myTest VALUES (3,1,5,'2000-01-13 00:00:00','2000-01-18 00:00:00',null);
insert into myTest VALUES (4,1,2,'2000-01-20 00:00:00','2000-01-22 00:00:00',null);
insert into myTest VALUES (5,2,7,'2000-01-21 00:00:00','2000-01-28 00:00:00',null);

预期产出

BatchID,ProductID,ParentBatchID 
1,1,0
2,1,1 --as it's from (01.08) is between #1's from (01.01) and to+1 (01.11)
3,1,1 --as it's from (01.13) is between #2's from (01.08) and to+1 (01.13), so it needs to inherit #2's parent batch ID: 1
4,1,0 --as it's not between #3's from and to, it's a new batch
5,2,0 --as it's a different product, different batch

---------- 有一个扩展的问题版本,如果我确定了父母,我需要用孩子的长度日来延长它的长度,我需要检查下一个孩子是否来自从 -> 到 + 前一个孩子的长度。坦率地说,我不知道如何实现这一点。---------- 扩展版的 - 第 4 行会有所不同

BatchID,ProductID,ParentBatchID 
1,1,0
2,1,1 --as it's from (01.08) is between #1's from (01.01) and to+1 (01.11)
3,1,1 --as it's from (01.13) is between #1's from (01.01) and to+1+#2's length (01.10+1+4=016), so it needs to inherit #2's parent batch ID: 1
4,1,1 --! ParentBatchID=1 ! as it's from (01.20) is between the from (01.01) and to+1+extended by all previous children's length (01.10+1+4+5=01.20), so it needs to inherit #3's parent batch ID: 1  
5,2,0 --as it's a different product, different batch

欢迎所有指导和帮助提前谢谢你

尼古拉


编辑

递归解决方案很棒,但仅适用于最有限的数据集。你能建议一种更具可扩展性的方法吗?

谢谢

4

1 回答 1

0
;with t as 
(
  select tt.BatchID, tt.Product, tt.fromDate, tt.toDate, 0 ParentBatchID, 1 lvl, tt.BatchID rootID
  from myTest tt
  where not exists(select 1 from myTest t 
                   where t.Product=tt.Product 
                     and tt.BatchID <> t.BatchID
                     and tt.fromDate between t.fromDate and dateadd(day, 1, t.toDate)
                  )

  union all

  select tt.BatchID, tt.Product, tt.fromDate, tt.toDate, t.BatchID, t.lvl+1, t.rootID
  from t
  INNER JOIN myTest tt
  on tt.Product = t.Product
  where tt.BatchID <> t.BatchID 
    and tt.fromDate between t.fromDate and dateadd(day, 1, t.toDate)
)
select BatchId, Product, ParentBatchID, rootId, lvl
from t
order by Product, fromDate, lvl

http://sqlfiddle.com/#!18/971f3/37

BatchId Product ParentBatchID   rootId  lvl
1   1   0   1   1
2   1   1   1   2
3   1   2   1   3
4   1   0   4   1
5   2   0   5   1
于 2018-02-28T11:17:34.060 回答