我有一个表,其中包含一列十进制值,例如:
id value size
-- ----- ----
1 100 .02
2 99 .38
3 98 .13
4 97 .35
5 96 .15
6 95 .57
7 94 .25
8 93 .15
我需要完成的工作有点难以描述,因此请耐心等待。我正在尝试做的是创建size
列的聚合值,每当前一行的总和为1时(根据降序排列),该列的值就会递增1 value
。结果看起来像这样:
id value size bucket
-- ----- ---- ------
1 100 .02 1
2 99 .38 1
3 98 .13 1
4 97 .35 1
5 96 .15 2
6 95 .57 2
7 94 .25 2
8 93 .15 3
我天真的尝试是保持运行SUM
,然后再保持CEILING
该值,但是它不能解决某些记录size
最终导致两个单独的存储桶总计的情况。下面的示例可以阐明这一点:
id value size crude_sum crude_bucket distinct_sum bucket
-- ----- ---- --------- ------------ ------------ ------
1 100 .02 .02 1 .02 1
2 99 .38 .40 1 .40 1
3 98 .13 .53 1 .53 1
4 97 .35 .88 1 .88 1
5 96 .15 1.03 2 .15 2
6 95 .57 1.60 2 .72 2
7 94 .25 1.85 2 .97 2
8 93 .15 2.00 2 .15 3
如您所见,如果我仅CEILING
在crude_sum
记录#8 上使用,则会将其分配给存储桶2。这是由于size
记录#5和#8被拆分到两个存储桶中引起的。取而代之的是,理想的解决方案是在每次总和达到1时重置总和,然后使该bucket
列递增并从当前记录SUM
的size
值开始进行新操作。因为记录的顺序对于此操作很重要,所以我包括了该value
列,该列旨在按降序排序。
我最初的尝试涉及对数据进行多次传递,一次执行SUM
操作,再执行一次操作CEILING
,等等。这是我创建crude_sum
列的示例:
SELECT
id,
value,
size,
(SELECT TOP 1 SUM(size) FROM table t2 WHERE t2.value<=t1.value) as crude_sum
FROM
table t1
在用于UPDATE
将值插入表中以供以后使用的操作中使用的值。
编辑:我想在解释这一点时再做一次尝试,所以就到这里。想象每个记录是一个物理项目。该项目具有与之关联的值,并且物理尺寸小于1。我有一系列容量恰好为1的存储桶,我需要根据所需物品的值(从最高到最低)确定要使用多少个存储桶,以及每个项目进入哪个存储桶。
物理项目不能同时存在于两个位置,因此必须位于一个存储桶或另一个存储桶中。这就是为什么我无法执行运行中的total + CEILING
解决方案的原因,因为那会使记录将其大小贡献给两个存储桶。
distinct_count
使事情变得复杂。Aaron Bertrand 对此类窗口工作在SQL Server上的选择进行了很好的总结。我使用了“古怪的更新”方法来计算distinct_sum
,您可以在SQL Fiddle上看到此方法,但这是不可靠的。