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

(C)

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

'A' 案例是最优选的!

我知道这种情况与组合有关。

在现实世界中 - 客户从商店获取物品,并且由于他与商店之间的协议,他每周五付款。付款金额不是物品的确切总和,例如:他得到 5 本书 50 欧元(= 250 欧元),周五他带来 150 欧元,所以前 3 本书是完美匹配的 - 3 * 50 = 150。我需要找到这3本书的ID!

任何帮助,将不胜感激!

4

3 回答 3

3

您可以在 MSSQL 中使用递归查询来解决这个问题。

SQLFiddle demo

第一个递归查询构建一个累积和 <= 150 的项目树。第二个递归查询获取累积和 = 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

如果您将问题限制为“两个数字相加为一个值”,则解决方案如下:

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

如果您还想要三个或更多数字的结果,您可以通过使用上述查询作为递归 SQL 的基础来实现。不要忘记指定最大递归深度!

于 2014-01-09T13:01:20.980 回答
0

要查找客户支付的书籍的 ID,您需要与客户有一张桌子,还有一张桌子来存储客户的订单以及他购买的产品。

否则就不可能知道付款是指什么产品。

于 2014-01-09T12:49:35.633 回答