わかりました、私は必ずしもそれが良い考えだと思うというよりも、挑戦のためにこれを行いました. 私は、カーソルの方が適切かもしれないと Aaron を信じる傾向があります。とにかく:
declare @Items table (ID int not null,LENGTH_IN_CM decimal(5,1) not null)
insert into @Items(ID,LENGTH_IN_CM) values
(1,1.0),
(2,1.0),
(3,9.0),
(4,5.0),
(5,15.0),
(6,3.0),
(7,6.0)
;With PossiblePages as (
select ID as MinID,ID as MaxID,LENGTH_IN_CM as TotalLength from @Items
union all
select MinID,MaxID + 1,CONVERT(decimal(5,1),TotalLength + LENGTH_IN_CM)
from
PossiblePages pp
inner join
@Items it
on
pp.MaxID + 1 = it.ID
where
TotalLength + LENGTH_IN_CM <= 20.0
), LongPages as (
select MinID,MAX(MaxID) as MaxID,MAX(TotalLength) as TotalLength from PossiblePages group by MinID
), FinalPages as (
select MinID,MaxID,TotalLength from LongPages where MinID = 1
union all
select lp.MinID,lp.MaxID,lp.TotalLength
from
LongPages lp
inner join
FinalPages fp
on
lp.MinID = fp.MaxID + 1
), PageNumbers as (
select MinID,MaxID,ROW_NUMBER() OVER (ORDER BY MinID) as PageNo
from FinalPages
)
select * from PageNumbers
結果:
MinID MaxID PageNo
----------- ----------- --------------------
1 4 1
5 6 2
7 7 3
各行にページ番号を割り当てたい場合は、元のテーブルに簡単に結合できるはずです。
PossiblePages
可能なすべてのページを計算します-すべての行について、その行がそのページの最初の行であるかのように機能し、それに追加できる行の数と、その行の範囲が表す合計の長さを計算します(ある場合があります)この式をよりクリーンな方法で計算する必要がありますが、現時点ではわかりません)。
LongPages
PossiblePages
次に、開始行番号ごとに、計算された最長値を見つけます。
最後にFinalPages
、最初のページから開始します (論理的には、1 で開始するID
必要があります。1 から開始することが保証されておらず、最も古いページを見つける必要がある場合は、いつでも別の計算を導入できます)。そして、次のページは、前の行よりも 1 つ上の行 ID から始まるページです。
は必要あり ませんがPageNumbers
、前述のとおり、元のテーブルに参加することを考えていました。
そして、コメンターが予測したように、これがうまく機能するとは思わない-サンプルだけで、これを計算するために少なくとも4つのテーブルスキャンが見られる.
ボーナス狂気。これは、テーブルを 3 回だけスキャンします。
;With PageRows as (
select ID as MinID,ID as MaxID,LENGTH_IN_CM as TotalLength from @Items where ID=1
union all
select MinID,MaxID + 1,CONVERT(decimal(5,1),TotalLength + LENGTH_IN_CM)
from
PageRows pr
inner join
@Items ir
on
pr.MaxID = ir.ID-1
where
TotalLength + LENGTH_IN_CM <= 20.0
union all
select ir.ID as MinID,ir.ID as MaxID,ir.LENGTH_IN_CM as TotalLength
from
PageRows pr
inner join
@Items ir
on
pr.MaxID = ir.ID-1
where
TotalLength + LENGTH_IN_CM > 20.0
), PageNumbers as (
select MinID,MAX(MaxID) as MaxID,ROW_NUMBER() OVER (ORDER BY MinID) as PageNo
from PageRows
group by MinID
)
select * from PageNumbers