次のような10進値の列を含むテーブルがあります。
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
列の集計値を作成することvalue
です。これは、に従って降順で、前の行の合計が1になるたびに1ずつ増加します。結果は次のようになります。
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
が2つの別々のバケットの合計の原因となるケースには対応していません。以下の例はこれを明確にするかもしれません:
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が2つのバケットに分割されていることが原因です。代わりに、理想的な解決策は、合計が1に達するたびに合計をリセットすることです。これにより、bucket
列が増分さSUM
れsize
、現在のレコードの値から新しい操作が開始されます。この操作ではレコードの順序が重要value
であるため、降順でソートすることを目的とした列を含めました。
私の最初の試みは、データに対して複数回のパスを実行することを含みましたSUM
。1回は操作を実行し、もう1回はそれを実行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未満です。ボリューム容量が正確に1の一連のバケットがあり、これらのバケットのうちいくつが必要か、およびアイテムの値に応じて各アイテムが入るバケットを、高いものから低いものへとソートする必要があります。
物理アイテムは一度に2か所に存在することはできないため、どちらか一方のバケットに存在する必要があります。これが、実行中の合計+ CEILING
ソリューションを実行できない理由です。これにより、レコードが2つのバケットにサイズを提供できるようになります。
distinct_count
事態を複雑にします。Aaron Bertrandは、この種のウィンドウ処理に関するSQL Serverのオプションの優れた要約を持っています。「風変わりな更新」メソッドを使用して計算しましたがdistinct_sum
、これはSQL Fiddleで確認できますが、これは信頼できません。