Eu tenho uma tabela que inclui uma coluna de valores decimais, como esta:
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
O que eu preciso realizar é um pouco difícil de descrever, por isso, tenha paciência comigo. O que estou tentando fazer é criar um valor agregado da size
coluna que incrementa em 1 cada vez que as linhas anteriores somam 1, quando em ordem decrescente de acordo com value
. O resultado seria algo parecido com isto:
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
Minha primeira tentativa ingênua foi manter um valor em execução SUM
e, em seguida, CEILING
esse valor, no entanto, ele não lida com o caso em que alguns registros size
acabam contribuindo para o total de dois depósitos separados. O exemplo abaixo pode esclarecer isso:
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
Como você pode ver, se eu fosse usar simplesmente CEILING
no crude_sum
registro # 8 seria atribuído a bucket 2. Isto é causado pelo size
de registros # 5 e # 8 sendo dividido em dois baldes. Em vez disso, a solução ideal é redefinir a soma cada vez que atingir 1, que depois incrementa a bucket
coluna e inicia uma nova SUM
operação começando com o size
valor do registro atual. Como a ordem dos registros é importante para esta operação, incluí a value
coluna, que deve ser classificada em ordem decrescente.
Minhas tentativas iniciais envolveram fazer várias passagens sobre os dados, uma vez para executar a SUM
operação, mais uma vez para CEILING
isso, etc. Aqui está um exemplo do que eu fiz para criar a crude_sum
coluna:
SELECT
id,
value,
size,
(SELECT TOP 1 SUM(size) FROM table t2 WHERE t2.value<=t1.value) as crude_sum
FROM
table t1
Que foi usado em um UPDATE
operação para inserir o valor em uma tabela para trabalhar posteriormente.
Edit: Eu gostaria de dar uma outra facada em explicar isso, então aqui vai. Imagine que cada registro é um item físico. Esse item tem um valor associado a ele e um tamanho físico menor que um. Eu tenho uma série de buckets com uma capacidade de volume de exatamente 1 e preciso determinar quantos desses buckets serão necessários e qual bucket cada item entra de acordo com o valor do item, classificado do maior para o menor.
Um item físico não pode existir em dois lugares ao mesmo tempo; portanto, ele deve estar em um balde ou no outro. É por isso que não consigo fazer uma CEILING
solução total + em execução , porque isso permitiria que os registros contribuíssem com seu tamanho para dois buckets.
distinct_count
complica as coisas. Aaron Bertrand tem um ótimo resumo de suas opções no SQL Server para esse tipo de trabalho de janelas. Usei o método "quirky update" para calcular distinct_sum
, que você pode ver aqui no SQL Fiddle , mas isso não é confiável.