私は次のクエリ(PostgreSQLの)提案:
WITH ZeroToOne (m, n, y) AS (
SELECT m, n, random()
FROM inputs
CROSS JOIN generate_series(1, n)
), SumToM (m, n, y, x) AS (
SELECT m, n, y, y * m/sum(y) OVER (PARTITION BY m, n)
FROM zerotoone
), MissingToM (m, n, l) AS (
SELECT m, n, m - sum(floor(x))
FROM sumtom
GROUP BY m, n
)
SELECT m, n, y, x, l,
CASE
WHEN row_number() OVER (PARTITION BY m, n ORDER BY x - floor(x) DESC) > l
THEN floor(x)
ELSE ceil(x)
END AS v
FROM missingtom
NATURAL JOIN sumtom;
のみ興味深い値をmであり、nおよびV。私は説明のために他の値を残しました。
Iが実行中で、例として以下の入力の場合とクエリをステップう
:
SELECT * FROM inputs;
m | n
----+---
20 | 4
30 | 4
42 | 3
(3 rows)
最初のCTE(ZeroToOne)は、各入力の場合、コールは[1,0]の範囲内n
ランダムな値を計算しますこれらの値y
:
m | n | y
----+---+---------------------
20 | 4 | 0.374425032641739
20 | 4 | 0.644279096741229
20 | 4 | 0.626386553514749
20 | 4 | 0.320786282420158
30 | 4 | 0.848764919675887
30 | 4 | 0.268079651053995
30 | 4 | 0.250213726423681
30 | 4 | 0.497460773680359
42 | 3 | 0.571454062592238
42 | 3 | 0.00338772451505065
42 | 3 | 0.139226260595024
第二CTE(SumToM)はm
によって各y
値を乗算し、入力された場合の値の和で結果を分割します。結果として、入力対(M、N)のためx
の全てを合計するm
を与える:
m | n | y | x
----+---+---------------------+-------------------
20 | 4 | 0.374425032641739 | 3.80924177094873
20 | 4 | 0.644279096741229 | 6.55462277759638
20 | 4 | 0.626386553514749 | 6.37259161753762
20 | 4 | 0.320786282420158 | 3.26354383391728
30 | 4 | 0.848764919675887 | 13.6565766414436
30 | 4 | 0.268079651053995 | 4.3133855037604
30 | 4 | 0.250213726423681 | 4.02592384820881
30 | 4 | 0.497460773680359 | 8.00411400658722
42 | 3 | 0.571454062592238 | 33.6117414945302
42 | 3 | 0.00338772451505065 | 0.199258922297338
42 | 3 | 0.139226260595024 | 8.18899958317244
mはx
値の整数部分の合計よりも大きいことは明らかです。 2つの合計(x値の和とx値の整数部分の合計)の差がn
未満であることもわかります。だから今のアイデアは多くの数字を切り上げなければならず、どれだけ切り捨てなければならないのかということを数えることです。第三のCTE(MissingToM)のL値は切り上げされる値の数である:
m | n | l
----+---+---
20 | 4 | 2
30 | 4 | 1
42 | 3 | 1
数の分布が均一のままであることを確実にするために、我々は、と最高の小数部分を有する数値を切り上げ最後のクエリ:
m | n | y | x | l | v
----+---+---------------------+-------------------+---+----
20 | 4 | 0.374425032641739 | 3.80924177094873 | 2 | 4
20 | 4 | 0.644279096741229 | 6.55462277759638 | 2 | 7
20 | 4 | 0.626386553514749 | 6.37259161753762 | 2 | 6
20 | 4 | 0.320786282420158 | 3.26354383391728 | 2 | 3
30 | 4 | 0.848764919675887 | 13.6565766414436 | 1 | 14
30 | 4 | 0.268079651053995 | 4.3133855037604 | 1 | 4
30 | 4 | 0.250213726423681 | 4.02592384820881 | 1 | 4
30 | 4 | 0.497460773680359 | 8.00411400658722 | 1 | 8
42 | 3 | 0.571454062592238 | 33.6117414945302 | 1 | 34
42 | 3 | 0.00338772451505065 | 0.199258922297338 | 1 | 0
42 | 3 | 0.139226260595024 | 8.18899958317244 | 1 | 8
同じ構成(M、N)は、入力テーブルに数回発生した場合、クエリは失敗しますように、私はそれに主キー制約を追加しますため
ALTER TABLE inputs ADD PRIMARY KEY (m, n);
感謝通知するation。しかしここであなたは質問をすることになっています – RiggsFolly
+++これは実際には本当に厳しいSQLの質問です。私は挑戦します! –
@RiggsFollyこの質問は、特定の言語機能を使用するSQLソリューションを求めています。入力と出力を指定します。それは質問に答えるのを助けるために、3つの他の言語のSOソリューションを強調します。あなたの意見では、正確に何が欠けていますか?疑問符? – Sim