Select X 列总和大于或等于 Y 列的所有行

Select all rows where the sum of column X is greather or equal than Y

我需要找一组拍品来满足X件物品的需求。我不能用聚合函数来做,在我看来我需要的不仅仅是 window 函数,你知道什么可以帮助我解决这个问题吗?

比如我有1件需求,查询应该是return数量大于等于1的任意手数。但是如果我有15件需求,就没有手数有了这种可用性,所以它应该 return 很多 10 个,另一个有 5 个,或者 10 个中的一个和 3 个中的两个,等等

使用像 Java 这样的编程语言这很简单,但是使用 SQL 可能吗?我试图通过销售功能来实现它,但我找不到一种方法来添加当前行的可用数量,直到达到所需数量。

SELECT  id,VC_NUMERO_LOTE,SF_FECHA_CREACION,SI_ID_M_ARTICULO,VI_CANTIDAD,NEXT, VI_CANTIDAD + NEXT AS TOT FROM (
SELECT row_number() over (ORDER BY SF_FECHA_CREACION desc) id ,VC_NUMERO_LOTE,SF_FECHA_CREACION,SI_ID_M_ARTICULO,
VI_CANTIDAD,LEAD(VI_CANTIDAD,1)  OVER (ORDER BY SF_FECHA_CREACION desc) as NEXT FROM PUBLIC.M_LOTE WHERE SI_ID_M_ARTICULO = 44974
AND  VI_CANTIDAD > 0 ) AS T
WHERE   MOD(id, 2) != 0

我尝试使用 lead 对奇数记录求和,但我发现这不是正确的方法,有什么建议吗?

你需要这样的 recursive query:

demo:db<>fiddle

WITH RECURSIVE lots_with_rowcount AS (       -- 1
    SELECT 
        *, 
        row_number() OVER (ORDER BY avail_qty DESC) as rowcnt
    FROM mytable
), lots AS (                                 -- 2
    SELECT                                   -- 3
        lot_nr,
        avail_qty,
        rowcnt,
        avail_qty as total_qty
    FROM lots_with_rowcount
    WHERE rowcnt = 1
    
    UNION
    
    SELECT 
        t.lot_nr,
        t.avail_qty,
        t.rowcnt,
        l.total_qty + t.avail_qty           -- 4
    FROM lots_with_rowcount t
    JOIN lots l ON t.rowcnt = l.rowcnt + 1
        AND l.total_qty < --<your demand here>
)
SELECT * FROM lots                          -- 5
  1. 此 CTE 仅为每条记录提供行计数,可在递归中用于连接下一条记录。
  2. 这是递归 CTE。递归 CTE 包含两部分:初始 SELECT 语句和递归。
  3. 开头部分:查询avail_qty值最大的批次记录。当然,您可以按照您喜欢的任何顺序订购它们。大多数数量首先产生最小的输出。
  4. UNION 递归部分之后:此处当前行加入了前一个输出 AND 作为附加条件:仅当前一个输出不加入时才加入符合您的需求值。在这种情况下,下一个 total_qty 值是使用前一个和当前 qty 值计算的。
  5. 递归结束,当没有留下符合连接条件的记录时。然后就可以SELECT整个递归输出了。

注意:如果您的需求总量高于所有可用数量,这将 return 整个 table 因为只要未达到需求或您的 table结束。你应该在之前添加一个查询,检查这个:

SELECT SUM(avail_qty) > demand FROM mytable

这是一个使用(慢)循环的简单老式 PL/pgSQL 版本。 return仅以批号为例。基本上它所做的是 return 特定订单中特定 item_id 的批号(反映所需的业务规则)并分配可用数量,直到分配的数量等于或超过所需数量。

create function get_lots(required_item integer, required_qty integer) returns setof text as
$$
declare
    r record;
    allocated_qty integer := 0;
begin
for r in select * from lots where item_id = required_item order by <your biz-rule> loop
    return next r.lot_number;
    allocated_qty := allocated_qty + r.available_qty;
    exit when allocated_qty >= required_qty;
end loop;
end;
$$ language plpgsql;

-- Use 
select lot_id from get_lots(1, 17) lot_id;

我感激地 fiddle 和 S-Man 的 fiddle 转了一圈,找到了一个查询,至少更容易理解

select lot_nr, avail_qty, tot_amount from 
(select lot_nr, avail_qty,
  sum(avail_qty) over (order by avail_qty desc rows between unbounded preceding and current row) as tot_amount,
  sum(avail_qty) over (order by avail_qty desc rows between unbounded preceding and current row) - avail_qty as last_amount
from mytable) amounts
where last_amount < 15 -- your amount here

所以这列出了所有前行(按 avail_qty 降序排列)尚未达到限制的所有行