0

これはちょっと複雑な質問ですので、ご容赦ください。一連の整数を返すクエリがあるとします。

2387
3357
3471
4885
5867
6170
8170
9777
12970
13190
17670
20470
160159

それらがあなたにとってどのように機能するかを見るのが難しい場合でも、これらの明白なことはすべて私にとって何かを意味します. 簡単にするために、それらは測定値を表します。今、私の最初の試みは、特定のデータベースの値を、アップロード プロセスで取得した数値と照合することです。この場合、照合したい37,174

明らかに、探している金額に一致するレコードは 1 つもないことがわかります。私の本当の質問は、特定の金額の組み合わせが私が探している金額になるかどうかを確認する方法があるかどうかです. できれば SQL クエリに組み込むことができるものを探していますが、すべての処理に C# を使用しています。いただければ幸いです。私はGoogle検索を試みましたが、質問の言い回しの繊細さのために、関連/有用なものを見つけることができませんでした. まだ初心者なので、これを可能にする C# のメソッドやクラス、または Postgres の機能だけがあるかどうかはわかりません。

編集**ループを使用してそれを行う方法は知っていますが、それはパフォーマンスの悪い選択になることはわかっています。

4

5 に答える 5

1

SQL でこれを行う唯一の方法は、ブルート フォース アプローチです。たとえば、次のクエリでは、3 つの数値のすべての組み合わせが考慮されます。

select *
from t t1 join
     t t2
     on t1.val < t2.val join
     t.t3
     on t2.val < t3.val
where t1.val + t2.val + t3.val = 37174;

組み合わせは、最小値から最大値の順に並べられ、重複はありません。

目標に最も近い合計が必要な場合は、次のようにすることができます。

select 
from t t1 join
     t t2
     on t1.val < t2.val join
     t.t3
     on t2.val < t3.val
order by abs(t1.val + t2.val + t3.val - 37174)
limit 1;

最大 3 つの数値が必要な場合は、リストに値 0 を含めます。

そして、これらはすべて固定数の結合に一般化されます。

可変数を実行するには、再帰クエリを使用する必要があります。

このタイプの検索では、たとえば C# よりも SQL を使用する利点が 1 つあります。SQL はデフォルトでマルチスレッド並列処理を利用できます。

于 2013-05-29T16:02:23.287 に答える
1

次のようなものを試してください:

WITH RECURSIVE match(val, res) AS
(SELECT st.val , 1234 - st.val as res
 FROM your_table st
 WHERE 1234 - st.val >= 0
 UNION ALL
 SELECT nt.val,  match.res - nt.val 
 FROM your_table nt
 JOIN match ON match.res - nt.val >= 0
),

 final_match (val, res) AS
(SELECT match.val , match.res
 FROM match 
 WHERE match.res = 0
 UNION ALL
 SELECT match.val,  match.res
 FROM match
 JOIN final_match ON final_match.val = match.res
)

SELECT *
FROM final_match
ORDER BY res DESC;

アイデア-合計につながる可能性のある数値のすべての組み合わせを再帰的に構築すること。次に、次のいずれかを選択します。your_number - sum = 0

于 2013-05-29T16:19:55.217 に答える
1

コンビナトロニクス ライブラリの使用:

var values = new int[] { 1, 2, 3, 4, 5};
var target = 9;
var candidates = Enumerable.Range(1,values.Count())
                           .SelectMany(x => new Combinations<int>(values, x))
                           .Where(x => x.Sum() == target);

これにより、目標値に一致するすべての可能な組み合わせが得られます。FirstOrDefault()最初のもの ( を使用) を好むか、さらにロジックを適用するかは、あなた次第です。

あなたの例では、合計で になる組み合わせはありません37174

于 2013-05-29T16:15:30.370 に答える
1

数が増えると、オプションの数は指数関数的に増加します。

例えば:

数字が 3 つある場合は、7 つの組み合わせをチェックする必要があります。

A, B, C, A+B, A+C, B+C, A+B+C 

4つあると、

A, B, C, D, 
A+B, A+C, A+D, B+C, B+D, C+D,
A+B+C, A+B+D, A+C+D, B+C+D
A+B+C+D

等々。

だから私は、いいえ、絶対に答えを見つけるための簡単な SQL 方法はありません。

ただし、クロス結合を使用して、より単純なソリューションを見つけることができます。

例:テーブルtに値を含むフィールド i がある場合、結果に 0 の数字を追加して...

insert t (i)
select 0 union
select 2387 union
select 3357 union
select  3471 union
select  4885 union
select  5867 union
select  6170 union
select 8170 union
select  9777 union
select  12970 union
select  13190 union
select  17670 union
select  20470 union
select  160159

select *, t1.i + t2.i + t3.i + t4.i + t5.i + t6.i + t7.i
 from t t1
    cross join t t2 
    cross join t t3 
    cross join t t4 
    cross join t t5
    cross join t t6
    cross join t t7
where t1.i+t2.i+t3.i+t4.i+t5.i+t6.i+t7.i = 37174    

どちらがあなたに組み合わせを与えるでしょう...

2387    3471    4885    13190   4885    4885    3471

現在、重複が許可されていないという制限がある場合があります。その場合、データからの解決策はありません

于 2013-05-29T16:15:49.637 に答える
0

SQL Server 構文の使用 - 再帰 CTE に相当する postgres があるかどうかわかりません

;with cte as
(
    select  cast(val as varchar(MAX)) as valtxt
    ,       val
    ,       val as summed
    from #temp

    union all
    select  C.valtxt +' + ' + CAST(C2.val as varchar(max))
    ,       C2.val
    ,       C.summed + C2.val
    from cte C
    inner join #temp C2
    on c.val < C2.val
    where C.summed <= 37174
)
select top 1 valtxt, summed from cte order by ABS(summed - 37174)

(#temp は値を含むテーブルです)

于 2013-05-29T16:30:54.470 に答える