sql - Postgres : limit by the results of a sum function

标签 sql postgresql aggregate-functions plpgsql common-table-expression

CREATE TABLE inventory_box (
 box_id varchar(10),
 value   integer
);

INSERT INTO inventory_box VALUES ('1', 10), ('2', 15), ('3', 20);

我准备了一个sql fiddle与模式。

我想选择合计值(value)在20以上的库存箱列表

possible result 1. box 1 + box 2 (10 + 15 >= 20) 

这是我现在正在做的事情:

SELECT * FROM inventory_box LIMIT 1 OFFSET 0;
-- count on the client side and see if I got enough
-- got 10
SELECT * FROM inventory_box LIMIT 1 OFFSET 1;
-- count on the client side and see if I got enough
-- got 15, add it to the first query which returned 10
-- total is 25, ok, got enough, return answer

我正在寻找一种一旦达到目标值就会停止扫描的解决方案

最佳答案

一种可能的方法是按 box_id 顺序扫描表,直到总数超过 30,然后返回所有前面的行加上使总和超过限制的行。请注意,当达到总和时扫描不会停止,它会对整个表进行总计,然后返回结果以选择结果。

http://sqlfiddle.com/#!15/1c502/4

SELECT
  array_agg(box_id ORDER BY box_id) AS box_ids,
  max(boxsum) AS boxsum
FROM
(
  SELECT
    box_id,
    sum(value) OVER (ORDER BY box_id) AS boxsum,
    sum(value) OVER (ORDER BY box_id ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS prevboxsum
  FROM 
    inventory_box
) x
WHERE prevboxsum < 30 OR prevboxsum IS NULL;

但实际上,在 SQL 中以通用且可靠的方式(或根本不这样做)会非常可怕。

如果愿意,您可以ORDER BY value ASC 而不是ORDER BY box_id;这将从最小到最大添加框。但是,如果您随后从池中移除所有小方 block 并再次运行并重复,这将发生灾难性的失败。很快它就会低效地将两个大盒子混在一起。

要解决一般情况下的这个问题,找到最小组合是一个困难的优化问题,可能受益于不精确的基于样本和概率的方法。

要按顺序扫描表直到总和达到目标,锁定表然后使用 PL/PgSQL 从游标中读取行,该游标以 value 顺序返回行加上一个 array_agg (box_id) OVER(按值排序)sum(value) OVER(按值排序)。当您达到所需的总和时,返回当前行的数组。这不会产生一个最佳解决方案,但它会产生一个一个解决方案,而且我认为如果在地方。

关于sql - Postgres : limit by the results of a sum function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22623148/

相关文章:

postgresql - 更新时引用无效,那么,如何更新呢?

postgresql - 在 bash 中使用 psql 命令查询 postgresql 抛出错误 : relation "testschema.testtable" does not exist

sql - DB2 SQL 更新表值

sql - 在 MS Access 查询中使用多值字段

sql - TransactionScope IsolationLevel 未应用于 Azure

mysql - 计算多个sql表的百分比

sql - 左连接和 count() 缺少行所需的解释

sql - 如何在sql server中计算平均值

在 postgresql 中使用 IN 子句的性能

mysql从另一个表更新表