Mam tabelę, która zawiera kolumnę wartości dziesiętnych, takich jak ta:
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
To, co muszę osiągnąć, jest trochę trudne do opisania, więc proszę o wyrozumiałość. To, co próbuję zrobić, to utworzyć zagregowaną wartość size
kolumny, która zwiększa się o 1 za każdym razem, gdy poprzednie wiersze sumują się do 1, gdy w porządku malejącym zgodnie z value
. Wynik wyglądałby mniej więcej tak:
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
Moja naiwna pierwsza próba polegała na utrzymywaniu działania, SUM
a następnie na CEILING
tej wartości, jednak nie dotyczy to przypadku, w którym niektóre rekordy size
przyczyniają się w sumie do dwóch oddzielnych segmentów. Poniższy przykład może to wyjaśnić:
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
Jak widać, gdybym po prostu używać CEILING
na crude_sum
płycie # 8 będzie przypisany do wiadra 2. Jest to spowodowane przez size
zapisów # 5 i # 8 rozdzielona na dwa wiadra. Zamiast tego idealnym rozwiązaniem jest resetowanie sumy za każdym razem, gdy osiągnie 1, co następnie zwiększa bucket
kolumnę i rozpoczyna nową SUM
operację, rozpoczynając od size
wartości bieżącego rekordu. Ponieważ kolejność rekordów jest ważna dla tej operacji, dołączyłem value
kolumnę, która ma być sortowana w kolejności malejącej.
Moje pierwsze próby obejmowały wielokrotne przekazywanie danych, raz, aby wykonać SUM
operację, raz jeszcze CEILING
, itd. Oto przykład tego, co zrobiłem, aby utworzyć crude_sum
kolumnę:
SELECT
id,
value,
size,
(SELECT TOP 1 SUM(size) FROM table t2 WHERE t2.value<=t1.value) as crude_sum
FROM
table t1
Który został użyty w UPDATE
operacji, aby wstawić wartość do tabeli do późniejszej pracy.
Edycja: Chciałbym wziąć kolejny kłopot z wyjaśnieniem tego, więc proszę bardzo. Wyobraź sobie, że każdy rekord jest przedmiotem fizycznym. Ten przedmiot ma powiązaną z nim wartość i rozmiar fizyczny mniejszy niż jeden. Mam serię wiader o pojemności dokładnie 1 i muszę określić, ile z tych wiader potrzebuję i które wiadro zawiera każdy element zgodnie z wartością przedmiotu, posortowane od najwyższej do najniższej.
Przedmiot fizyczny nie może istnieć w dwóch miejscach jednocześnie, więc musi znajdować się w jednym lub drugim wiadrze. Dlatego nie mogę wykonać działającego CEILING
rozwiązania total + , ponieważ pozwoliłoby to rekordom na zwiększenie ich rozmiaru do dwóch segmentów.
distinct_count
komplikuje rzeczy. Aaron Bertrand ma świetne podsumowanie twoich opcji na SQL Server dla tego rodzaju okienkowania. Użyłem metody „dziwacznej aktualizacji” do obliczenia distinct_sum
, którą można zobaczyć tutaj na SQL Fiddle , ale jest to niewiarygodne.