我的问题与我之前发布的问题非常类似: Sql - SELECT rows until the sum of a row is a certain value
总结一下,我需要返回行,直到达到一定的总和,但这次的不同之处在于,我需要找到最适合这个总和的,我的意思是,它没有'必须是顺序的。例如:
我们说我有5张来自客户1的未付款收据:
Receipt_id: 1 | Amount: 110€
Receipt_id: 2 | Amount: 110€
Receipt_id: 3 | Amount: 130€
Receipt_id: 4 | Amount: 110€
Receipt_id: 5 | Amount: 190€
因此,客户1应该向我支付220欧元。
现在我需要选择收据,直到这个220欧元的金额得到满足,它可能是一个直接的顺序,如(收据1 +收据2)或不是特定的顺序,如(收据1 +收据4) ,任何这些情况都适合。
我正在使用SQL Server 2016。
任何其他问题,请随时提出。
提前感谢您的帮助。
答案 0 :(得分:2)
此查询应解决此问题。
这是一个非常危险的查询(包含递归CTE),所以请小心!
您可以在此处找到一些文档:https://www.essentialsql.com/recursive-ctes-explained/
WITH the_data as (
SELECT *
FROM (
VALUES (1, 1, 110),(1, 2,110),(1, 3,130),(1, 4,110),(1, 5,190),
(2, 1, 10),(2, 2,20),(2, 3,200),(2, 4,190)
) t (user_id, receipt_id, amount)
), permutation /* recursive used here */ as (
SELECT
user_id,
amount as sum_amount,
CAST(receipt_id as varchar(max)) as visited_receipt_id,
receipt_id as max_receipt_id,
1 as i
FROM the_data
WHERE amount > 0 -- remove empty amount
UNION ALL
SELECT
the_data.user_id,
sum_amount + amount as sum_amount,
CAST(concat(visited_receipt_id, ',', CAST(receipt_id as varchar))as varchar(max)) as visited_receipt_id,
receipt_id as max_receipt_id ,
i + 1
FROM the_data
JOIN permutation
ON the_data.user_id = permutation.user_id
WHERE i < 1000 -- max 1000 loops, means any permutation with less than 1000 different receipts
and receipt_id > max_receipt_id -- in order that sum in komutatif , we can check the sum in any unique order ( here we take the order of the reciept_id in fact we do not produce any duplicates )
-- AND sum_amount + amount <= 220 -- ignore everything that is bigger than the expected value (optional)
)
SELECT *
FROM permutation
WHERE sum_amount = 220
为了每个user_id只选择一个组合,用
替换上一个查询的最后三行SELECT *
FROM (
SELECT *, row_number() OVER (partition by user_id order by random() ) as r
FROM permutation
WHERE sum_amount = 220
) as t
WHERE r = 1
答案 1 :(得分:0)
如果您的目标只是为了达到您的价值而只收取2个收据,这可能是一个解决方案:
DECLARE @TARGET INT = 220 --SET YOUR TARGET
, @DIFF INT
, @FIRSTVAL INT
SET @FIRSTVAL = (
SELECT TOP 1 AMOUNT
FROM myRECEIPTS
ORDER BY RECEIPT_ID ASC
)
SELECT TOP 1 *
FROM myRECEIPTS
WHERE AMOUNT = @TARGET - @FIRSTVAL
ORDER BY RECEIPT_ID ASC
答案 2 :(得分:0)
此代码将执行此操作:
declare @sum1 int
declare @numrows int
set @numrows= 1
set @sum1 =0
while (@sum1 < 10)
begin
select top (@numrows) @sum1=sum(sum1) from receipts
set @numrows +=1
end
select top(@numrows) * from receipts