У меня есть таблица, которая включает в себя столбец десятичных значений, таких как это:
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, и мне нужно определить, сколько из этих сегментов мне понадобится и в какой блок входит каждый элемент, в соответствии со стоимостью элемента, отсортированного от наивысшего к наименьшему.
Физический предмет не может существовать в двух местах одновременно, поэтому он должен находиться в одном ведре или другом. Вот почему я не могу выполнить CEILING
решение по промежуточному итогу + , потому что это позволило бы записям вносить свой размер в два сегмента.
distinct_count
усложнять ситуацию. Аарон Бертран (Aaron Bertrand) имеет отличную сводку ваших опций на SQL Server для такой работы с окнами. Я использовал метод «причудливого обновления» для расчета distinct_sum
, который вы можете увидеть здесь на SQL Fiddle , но это ненадежно.