我的数据为:
ID LENGTH_IN_CM
1 1.0
2 1.0
3 9.0
4 5.0
5 15.0
6 3.0
7 5.0
我知道页面长20厘米,想要计算每个项目的页面。
因此,例如id为1,2,3和4的项目将位于第一页(1.0 + 1.0 + 9.0 + 5.0 <20.0),但5和6将在第二页上,7则在第三页上。
是否可以在不使用光标的情况下计算页码?
答案 0 :(得分:6)
好吧,我为挑战做了更多的事情,而不是因为我认为这是一个好主意。我倾向于相信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
从第一页开始(从逻辑上讲,必须是以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
答案 1 :(得分:0)
这也有效。告诉我为什么这些方法不能满足您的需求
declare @mytable as table(id int, LENGTH_IN_CM int)
insert into @mytable values
(1,1),
(2,1),
(3,9),
(4,5),
(5,15),
(6,3),
(7,6);
Select t.id ,
(select floor(SUM(LENGTH_IN_CM)/20.0)+1 page from @myTable where id<=t.id)
from @mytable t
id Page
----------- ---------------------------------------
1 1
2 1
3 1
4 1
5 2
6 2
7 3
(7 row(s) affected)