MSSQL查找发起者批处理 - 没有游标

问题描述 投票:1回答:1

我正在寻找有关SQL 2016以下内容的一些帮助

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

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

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

到目前为止,我用光标做了这个,但是你知道RBAR的表现。 *当当前fromDate介于之前和之后+ 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

----------有一个扩展的问题版本,如果我识别parrent我需要延长它的长度与孩子的长度一天,我需要检查下一个孩子,如果它来自在从 - >到+之前的childern长度。坦率地说,我不知道如何实现这一点。 ----------扩展版本 - 第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

欢迎提供所有指导和帮助。提前感谢您


编辑

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

谢谢

sql-server rbar
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
© www.soinside.com 2019 - 2024. All rights reserved.