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:
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
- 此 CTE 仅为每条记录提供行计数,可在递归中用于连接下一条记录。
- 这是递归 CTE。递归 CTE 包含两部分:初始
SELECT
语句和递归。
- 开头部分:查询
avail_qty
值最大的批次记录。当然,您可以按照您喜欢的任何顺序订购它们。大多数数量首先产生最小的输出。
- 在
UNION
递归部分之后:此处当前行加入了前一个输出 AND 作为附加条件:仅当前一个输出不加入时才加入符合您的需求值。在这种情况下,下一个 total_qty
值是使用前一个和当前 qty
值计算的。
- 递归结束,当没有留下符合连接条件的记录时。然后就可以
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 降序排列)尚未达到限制的所有行
我需要找一组拍品来满足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:
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
- 此 CTE 仅为每条记录提供行计数,可在递归中用于连接下一条记录。
- 这是递归 CTE。递归 CTE 包含两部分:初始
SELECT
语句和递归。 - 开头部分:查询
avail_qty
值最大的批次记录。当然,您可以按照您喜欢的任何顺序订购它们。大多数数量首先产生最小的输出。 - 在
UNION
递归部分之后:此处当前行加入了前一个输出 AND 作为附加条件:仅当前一个输出不加入时才加入符合您的需求值。在这种情况下,下一个total_qty
值是使用前一个和当前qty
值计算的。 - 递归结束,当没有留下符合连接条件的记录时。然后就可以
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 降序排列)尚未达到限制的所有行