SQL Server:选择行的总和等于特定值

4

这里有一个表格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'

预期结果是:-
(A)
id  num
-------
 1  50
 8  100

(B)
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!

任何帮助都将不胜感激!


1
或者是(3,90);(6,60),或者是(9,70);(10,80),为什么第一种选项是“最优先的”? - Lamak
我认为这个问题需要采用迭代方法,而这并不是 SQL 的强项。 - Andriy M
1
https://dev59.com/qUvSa4cB1Zd3GeqPifOd - Mikael Eriksson
@Lamak 第一个选项是“最优选”的,因为它使用的行数较少。但这是可选的。 - armen
正如@Lamak所说:3(90)和6(60)9(70)和10(80)之间的组合也会导致2行。 - Kiril Rusev
哦,我的错误,任何一个都可以完成工作。关键是要有最少的行数。 - armen
3个回答

3
您可以在MSSQL中使用递归查询来解决此问题。
第一个递归查询构建了一个项目树,其累积总和<= 150。第二个递归查询获取累积总和= 150的叶子,并输出所有到其根的路径。此外,在最终结果中按ItemsCount排序,因此您将首先获得首选组(具有最小的项目数)。 SQLFiddle演示
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

完美!第一行是预期结果!谢谢。 - armen

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的基础来实现。不要忘记指定最大递归深度!

我对递归并没有太多的了解。我会阅读更多关于递归的内容来尝试你的方法。 - armen

0
要找到客户正在支付的书籍的ID,您需要拥有一个包含客户信息的表格,以及另一个用于存储客户订单和他购买的产品的表格。
否则,就无法知道付款所涉及的产品是什么。

当然有客户端ID,我只是将问题最小化了,所以该表仅包含一个客户端的信息。 - armen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接