J'ai un tableau qui comprend une colonne de valeurs décimales, comme celle-ci:
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
Ce que je dois accomplir est un peu difficile à décrire, alors soyez indulgent avec moi. Ce que j'essaie de faire est de créer une valeur agrégée de la size
colonne qui augmente de 1 à chaque fois que les lignes précédentes totalisent 1, en ordre décroissant selon value
. Le résultat ressemblerait à ceci:
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
Ma première tentative naïve a été de conserver une valeur en cours SUM
, puis CEILING
cette valeur, mais elle ne gère pas le cas où certains enregistrements size
finissent par contribuer au total de deux compartiments distincts. L'exemple ci-dessous pourrait clarifier ceci:
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
Comme vous pouvez le voir, si je devais simplement utiliser CEILING
sur l' crude_sum
enregistrement # 8 serait affecté au compartiment 2. Cela est dû au fait que les size
enregistrements # 5 et # 8 sont répartis sur deux compartiments. Au lieu de cela, la solution idéale consiste à réinitialiser la somme chaque fois qu'elle atteint 1, ce qui incrémente ensuite la bucket
colonne et commence une nouvelle SUM
opération à partir de la size
valeur de l'enregistrement en cours. Étant donné que l'ordre des enregistrements est important pour cette opération, j'ai inclus la value
colonne, qui est destinée à être triée par ordre décroissant.
Mes premières tentatives ont consisté à effectuer plusieurs passages sur les données, une fois pour effectuer l' SUM
opération, une fois de plus pour CEILING
cela, etc. Voici un exemple de ce que j'ai fait pour créer la crude_sum
colonne:
SELECT
id,
value,
size,
(SELECT TOP 1 SUM(size) FROM table t2 WHERE t2.value<=t1.value) as crude_sum
FROM
table t1
Qui a été utilisé dans une UPDATE
opération pour insérer la valeur dans une table pour travailler plus tard.
Edit: Je voudrais essayer de nouveau d'expliquer cela, alors voici. Imaginez que chaque enregistrement soit un élément physique. Cet élément a une valeur qui lui est associée et une taille physique inférieure à un. J'ai une série de seaux d'une capacité volumique d'exactement 1, et je dois déterminer combien de ces seaux j'aurai besoin et dans quel seau chaque article va en fonction de la valeur de l'article, trié du plus élevé au plus bas.
Un élément physique ne peut pas exister à deux endroits à la fois, il doit donc être dans un seau ou dans l'autre. C'est pourquoi je ne peux pas faire une CEILING
solution total + en cours d'exécution , car cela permettrait aux enregistrements de contribuer leur taille à deux compartiments.
distinct_count
complique les choses. Aaron Bertrand a un excellent résumé de vos options sur SQL Server pour ce type de travail de fenêtrage. J'ai utilisé la méthode de "mise à jour décalée" pour calculer distinct_sum
, que vous pouvez voir ici sur SQL Fiddle , mais ce n'est pas fiable.