Ich habe eine Tabelle, die eine Spalte mit Dezimalwerten enthält, wie diese:
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
Was ich erreichen muss, ist etwas schwierig zu beschreiben. Bitte nehmen Sie Kontakt mit mir auf. Ich versuche, einen Gesamtwert der size
Spalte zu erstellen, der jedes Mal um 1 erhöht wird, wenn die vorhergehenden Zeilen in absteigender Reihenfolge zu 1 summieren value
. Das Ergebnis würde ungefähr so aussehen:
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
Mein naiver erster Versuch war, einen laufenden Wert SUM
und dann CEILING
diesen Wert beizubehalten. Er behandelt jedoch nicht den Fall, in dem einige Datensätze size
zu insgesamt zwei separaten Buckets beitragen. Das folgende Beispiel könnte dies verdeutlichen:
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
Wie Sie sehen können, wenn ich einfach zu bedienen waren CEILING
auf crude_sum
Rekord # 8 würde 2. zu Eimer zugeordnet werden diese durch die verursacht wird , size
von Datensätzen # 5 und # 8 , die geteilt in zwei Eimern. Stattdessen besteht die ideale Lösung darin, die Summe jedes Mal zurückzusetzen, wenn sie 1 erreicht. Dadurch wird die bucket
Spalte erhöht und eine neue SUM
Operation ab dem size
Wert des aktuellen Datensatzes gestartet. Da die Reihenfolge der Datensätze für diesen Vorgang wichtig ist, habe ich die value
Spalte eingefügt, die in absteigender Reihenfolge sortiert werden soll.
Meine ersten Versuche umfassten das Durchführen mehrerer Durchgänge über die Daten, einmal zum Ausführen des SUM
Vorgangs, noch einmal zum Durchführen CEILING
usw. Hier ist ein Beispiel dafür, was ich zum Erstellen der crude_sum
Spalte getan habe :
SELECT
id,
value,
size,
(SELECT TOP 1 SUM(size) FROM table t2 WHERE t2.value<=t1.value) as crude_sum
FROM
table t1
Dies wurde in einer UPDATE
Operation verwendet, um den Wert in eine Tabelle einzufügen, mit der später gearbeitet werden soll.
Bearbeiten: Ich würde gerne noch einmal versuchen, dies zu erklären, also geht es weiter. Stellen Sie sich vor, jeder Datensatz ist ein physischer Gegenstand. Diesem Element ist ein Wert zugeordnet und eine physische Größe von weniger als eins. Ich habe eine Reihe von Eimern mit einer Volumenkapazität von genau 1, und ich muss bestimmen, wie viele dieser Eimer ich benötige und in welchen Eimer jeder Artikel gemäß dem Wert des Artikels geht, sortiert vom höchsten zum niedrigsten.
Ein physischer Gegenstand kann nicht an zwei Orten gleichzeitig existieren, daher muss er sich in dem einen oder anderen Eimer befinden. Aus diesem Grund kann ich keine laufende Total + CEILING
-Lösung durchführen, da Datensätze dadurch ihre Größe auf zwei Buckets übertragen können.
distinct_count
erschwert das Erfordernis des Aufbockens die Dinge. Aaron Bertrand hat eine großartige Zusammenfassung Ihrer Optionen auf SQL Server für diese Art von Fensterarbeiten. Ich habe die "skurrile Update" -Methode verwendet, um zu berechnen distinct_sum
, die Sie hier auf SQL Fiddle sehen können , aber dies ist unzuverlässig.