需要 SQL 来选择行,直到列的总和达到最后一行不会完全消耗值的值
Posted
技术标签:
【中文标题】需要 SQL 来选择行,直到列的总和达到最后一行不会完全消耗值的值【英文标题】:Need SQL for selecting rows until sum of a column reach a value where the last row will not consume value in full 【发布时间】:2019-12-13 10:08:20 【问题描述】:您好,可能有许多类似的实现,但我在此处的其他线程中找不到一件事。所以一个新的qs。
表格包含两列。 BOX_ID 和 No_of_Chocolates。 行:
BOX_ID, No_of_Chocolates
1, 10
2, 5
3, 15
期望 SQL 查询应该根据我需要的巧克力数量返回。
案例 1:需要巧克力 =5 SQL 结果应该是:
1, 5
(意思是,我可以从第一个盒子里得到 5 块巧克力)
案例 2:需要巧克力 =10 SQL 结果应该是:
1, 10
案例 3:需要巧克力 =13 SQL 结果应该是:
1, 10
2, 3
(意思是,我需要从 Box-1 中取出所有东西,从 Box-2 中取出 3)
案例 4:需要的巧克力 = 22 SQL 结果应该是:
1, 10
2, 5
3, 7
案例 5:需要的巧克力 = 35 SQL 结果应该是:
1, 10
2, 5
3, 15
(即使没有 35 块巧克力,它也应该提供所有可用的巧克力)
编辑: 对不起,如果结果被误解...结果不会用逗号连接。它将是两列。
【问题讨论】:
您是否还需要使用尽可能少的行来执行此操作?如果是这样,那么它可能真的是一个动态规划问题。 想知道如果只用sql查询就可以得到它,看起来应该有一个实现这个任务的函数,然后在where子句的sql查询中使用它。例如:函数(应该是流水线的)将返回它选择的行的 id,由 ',' 分隔,并且作为输入参数,您应该提供所需的巧克力数量。然后你可以在 where 子句中使用它:Select .... from where id in (function_call(35)), 当你需要 35 块巧克力时。 嗨蒂姆,感谢您的回复。不,我不想用尽可能少的行来做。我将拥有按日期排序的值的表格。 您好 Bartoz,如果结果被误解,对不起...结果不会用逗号连接。它将是两列。 【参考方案1】:你可以做一个窗口求和并以此过滤:
select
box_id,
least(
:wanted - total_no_of_chocolates,
no_of_chocolates
) no_of_chocolates
from (
select
t.*,
coalesce(
sum(no_of_chocolates) over(
order by box_id
rows between unbounded preceding and 1 preceding
),
0
) total_no_of_chocolates
from mytable t
) t
where total_no_of_chocolates < :wanted
wanted
代表目标巧克力数量。
Demo on DB Fiddle:
:wanted = 10
的结果:
:wanted = 13
的结果:
:wanted = 22
的结果:
:wanted = 35
的结果:
【讨论】:
【参考方案2】:GMB 的解决方案是正确的。但我认为有一种更简单的方式来表达类似的逻辑。
我会使用累积和,但像这样:
select b.box_id,
least(:needed - sum_upto_box, no_of_chocolates) as from_this_box
from (select b.*,
sum(no_of_chocolates) over (order by box_id) - no_of_chocolates as sum_upto_box
from boxes b
) b
where sum_upto_box < :needed
【讨论】:
以上是关于需要 SQL 来选择行,直到列的总和达到最后一行不会完全消耗值的值的主要内容,如果未能解决你的问题,请参考以下文章