3

ここに表がありますT:-

id  num
-------
 1  50
 2  20
 3  90
 4  40
 5  10
 6  60
 7  30
 8  100
 9  70
10  80

以下は架空のSQLです

select *
from T
where sum(num) = '150'

期待される結果は次のとおりです:-

(ア)

id  num
-------
 1  50
 8  100

(ロ)

id  num
-------
 2  20
 7  30
 8  100

(ハ)

id  num
-------
 4  40
 5  10
 8  100

「A」ケースが最も好ましいです。

このケースが組み合わせに関連していることは知っています。

現実の世界では、クライアントは店から商品を受け取り、彼と店の間の合意により、毎週金曜日に支払います。支払い額はアイテムの正確な合計ではありません。たとえば、彼は 50 ユーロ ( = 250 ユーロ ) の本を 5 冊受け取り、金曜日に 150 ユーロを持ってきたので、最初の 3 冊の本は完全に一致します - 3 * 50 = 150.これらの 3 冊の本の ID を見つける必要があります。

どんな助けでも大歓迎です!

4

3 に答える 3

3

これを解決するには、MSSQL で再帰クエリを使用できます。

SQLFiddle demo

最初の再帰クエリは、累積合計が 150 以下のアイテムのツリーを構築します。また、順序付けされた最終結果では、ItemsCount優先グループ (最小項目数) が最初に取得されます。

WITH CTE as
( SELECT id,num,
         id as Grp,
         0 as parent,
         num as CSum,
         1 as cnt,
         CAST(id as Varchar(MAX)) as path
     from T where num<=150
  UNION all
  SELECT t.id,t.num,
         CTE.Grp as Grp, 
         CTE.id as parent,
         T.num+CTE.CSum as CSum,
         CTE.cnt+1 as cnt,
         CTE.path+','+CAST(t.id as Varchar(MAX)) as path
    from T 
  JOIN CTE on T.num+CTE.CSum<=150 
             and CTE.id<T.id 
),
BACK_CTE as
(select CTE.id,CTE.num,CTE.grp, 
         CTE.path ,CTE.cnt as cnt,
         CTE.parent,CSum 
    from CTE where CTE.CSum=150
  union all
  select CTE.id,CTE.num,CTE.grp,
         BACK_CTE.path,BACK_CTE.cnt, 
         CTE.parent,CTE.CSum 
   from CTE
   JOIN BACK_CTE on CTE.id=BACK_CTE.parent 
              and CTE.Grp=BACK_CTE.Grp
              and BACK_CTE.CSum-BACK_CTE.num=CTE.CSum
) 
select id,NUM,path, cnt as ItemsCount   from BACK_CTE order by cnt,path,Id
于 2014-01-09T13:59:16.887 に答える
1

問題を「どの2 つの数値の合計が値になるか」に限定すると、解決策は次のようになります。

SELECT t1.id, t1.num, t2.id,t2.num
FROM T t1 
INNER JOIN T t2
ON t1.id < t2.id
WHERE t1.num + t2.num  = 150

3 つ以上の数値の結果も必要な場合は、上記のクエリを再帰 SQL のベースとして使用することで実現できます。最大再帰深度を指定することを忘れないでください!

于 2014-01-09T13:01:20.980 に答える