6

私は次のようなデータを持っています:

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

ページの長さは 20cm で、各項目がどのページにあるかを計算したいと考えています。

たとえば、id 1、2、3、および 4 のアイテムは最初のページ (1.0 + 1.0 + 9.0 + 5.0 < 20.0) に配置されますが、5 と 6 は 2 番目に、7 は 3 番目のページに配置されます。

カーソルを使わずにページ番号を計算することはできますか?

4

2 に答える 2

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可能なすべてのページを計算します-すべての行について、その行がそのページの最初の行であるかのように機能し、それに追加できる行の数と、その行の範囲が表す合計の長さを計算します(ある場合があります)この式をよりクリーンな方法で計算する必要がありますが、現時点ではわかりません)。

LongPagesPossiblePages次に、開始行番号ごとに、計算された最長値を見つけます。

最後に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
于 2012-07-06T13:37:38.127 に答える
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)
于 2012-07-06T13:58:15.960 に答える