Tengo una tabla que incluye una columna de valores decimales, como este:
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
Lo que necesito lograr es un poco difícil de describir, así que tengan paciencia conmigo. Lo que intento hacer es crear un valor agregado de la size
columna que se incremente en 1 cada vez que las filas anteriores sumen 1, cuando están en orden descendente de acuerdo con value
. El resultado se vería así:
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
Mi primer intento ingenuo fue mantener un funcionamiento SUM
y luego CEILING
ese valor, sin embargo, no maneja el caso donde algunos registros size
terminan contribuyendo al total de dos cubos separados. El siguiente ejemplo podría aclarar esto:
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 puede ver, si simplemente usara CEILING
en el crude_sum
registro # 8 se asignaría al depósito 2. Esto se debe a que los size
registros # 5 y # 8 se dividen en dos depósitos. En cambio, la solución ideal es restablecer la suma cada vez que llega a 1, que luego incrementa la bucket
columna y comienza una nueva SUM
operación que comienza en el size
valor del registro actual. Debido a que el orden de los registros es importante para esta operación, he incluido la value
columna, que debe ordenarse en orden descendente.
Mis intentos iniciales han implicado hacer múltiples pases sobre los datos, una vez para realizar la SUM
operación, una vez más para CEILING
eso, etc. Aquí hay un ejemplo de lo que hice para crear la crude_sum
columna:
SELECT
id,
value,
size,
(SELECT TOP 1 SUM(size) FROM table t2 WHERE t2.value<=t1.value) as crude_sum
FROM
table t1
Que se utilizó en una UPDATE
operación para insertar el valor en una tabla para trabajar más tarde.
Editar: me gustaría dar otra puñalada para explicar esto, así que aquí va. Imagine que cada registro es un elemento físico. Ese artículo tiene un valor asociado y un tamaño físico menor que uno. Tengo una serie de cubos con una capacidad de volumen de exactamente 1, y necesito determinar cuántos de estos cubos necesitaré y en qué cubo entra cada artículo de acuerdo con el valor del artículo, ordenados de mayor a menor.
Un elemento físico no puede existir en dos lugares a la vez, por lo que debe estar en un cubo u otro. Es por eso que no puedo hacer una CEILING
solución total + , porque eso permitiría que los registros contribuyan con su tamaño a dos cubos.
distinct_count
complica las cosas. Aaron Bertrand tiene un excelente resumen de sus opciones en SQL Server para este tipo de trabajo de ventanas. He utilizado el método de "actualización peculiar" para calcular distinct_sum
, que puedes ver aquí en SQL Fiddle , pero esto no es confiable.