选择没有光标的列的总和

Pab*_*buc 6 sql-server stored-procedures sql-server-2008-r2

我的数据如下:

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
Run Code Online (Sandbox Code Playgroud)

我知道页面长20厘米,想要计算每个项目将在哪些页面上.

因此,例如id为1,2,3和4的项目将位于第一页(1.0 + 1.0 + 9.0 + 5.0 <20.0),但5和6将在第二页上,7在第三页上.

是否可以在不使用光标的情况下计算页码?

Dam*_*ver 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
Run Code Online (Sandbox Code Playgroud)

结果:

MinID       MaxID       PageNo
----------- ----------- --------------------
1           4           1
5           6           2
7           7           3
Run Code Online (Sandbox Code Playgroud)

如果要为每行分配页码,哪个应该很容易连接回原始表.

PossiblePages 计算每个可能的页面 - 对于每一行,它就好像该行是该页面上的第一行,然后确定可以追加多少行,以及该行范围所代表的总长度(可能是更清晰的方法来计算这个表达式,目前还不确定).

LongPages然后PossiblePages为每个起始行号找到计算的最长值.

最后,FinalPages从第一页开始(逻辑上,必须是以1开头的那一页ID- 如果你不能保证从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
Run Code Online (Sandbox Code Playgroud)