[英]Oracle PL/sql : Calculate sum of all possible number combinations
Oracle數據庫
假設我有 3 個盒子,里面有不同數量的物品(盒子的數量是固定的)
盒子編號和數量如下
B101 5
B102 5
B103 4
有一個容器,里面有一些物品
現有數量 - 2
容器容量 - 15
現在我想要box1,box2,box3,現有數量的所有可能組合的總和。
我將 select 只有總和 < 容量最適合的組合
所有組合都必須具有現有數量,因為我們不能忽略它
本案例的最終結果
框 1 + 框 2 + 現有數量 5+5+2,可容納 15 人。
需要一個 PL/SQL 塊來執行相同的活動
我將在記錄表中獲取盒子 ID 和盒子數量(用戶定義)
可能有更簡單的方法,但我會使用遞歸 CTE。 這是一個簡單的 SQL 示例,帶有額外的示例行:
create table boxes (id varchar2(4), qty number);
insert into boxes values ('B101',5);
insert into boxes values ('B102',5);
insert into boxes values ('B103',4);
insert into boxes values ('B104',9);
insert into boxes values ('B105',11);
insert into boxes values ('B106',2);
insert into boxes values ('B107',1);
with c (r, id, qty, lvl) as (
-- anchor query
select id as r, id, qty, 1 as lvl
from boxes
where qty + 2 < 15
union all
-- recursive query
select c.r || ',' || b.id, b.id, b.qty+c.qty, c.lvl+1
from boxes b
join c on c.id < b.id
where b.qty + c.qty + 2 < 15
)
select r, lvl, qty
from c
order by qty desc, lvl asc
;
這將顯示所有組合,最適合的在頂部。 我在級別上添加了二級排序,假設在平局的情況下,您希望每個容器的盒子數量最少。 但是您可能更喜歡每個容器的最大盒子數。
我還在join on c.id < b.id
而不是交叉連接,因為我認為你並不是真的想要所有組合,你想要所有唯一的組合,所以它更像是一個樹搜索。
以及作為 PL/SQL function 的示例:
create or replace function fit_boxes(existing_qty in number, capacity in number)
return varchar2
is
box_list varchar2(4000);
begin
with c (r, id, qty, lvl) as (
select id as r, id, qty, 1 as lvl
from boxes
where qty + existing_qty < capacity
union all
select c.r || ',' || b.id, b.id, b.qty+c.qty, c.lvl+1
from boxes b
join c on c.id < b.id
where b.qty + c.qty + existing_qty < capacity
)
select r into box_list
from c
order by qty desc, lvl asc
fetch first 1 row only
;
return box_list;
exception when NO_DATA_FOUND then
return 'No boxes fit'
end;
/
select fit_boxes(2,15) from dual;
最后,我猜你想要 sum <= capacity,但你的問題肯定是“sum < capacity”,所以我就是這樣寫的。 只需使用您的數據對其進行測試並確保其按預期工作即可。
編輯:當然,要解釋查詢邏輯 - 對於遞歸 CTE ,您從錨查詢開始並將其聯合到遞歸查詢(不斷從 CTE 本身迭代選擇)。
對於錨點,我們首先選擇所有可以放入容器中的單個框(其中 qty + 2 < 15)。 在我們的示例中,它們都適合,所以我們有 7 行,lvl 為 1。
對於遞歸部分,我們在容器c
中已經有 1 個或多個框,我們想看看b
中剩下的哪些框適合。 所以我們加入他們,使用c.id < b.id
來確保我們只查看b
中的框,這些框不在c
中。 一旦我們查看了所有的框,連接將返回 0 行並且遞歸將停止。
對於 CTE 中的 4 列 - r
顯示了到目前為止我們添加到容器中的所有框, id
顯示了最近添加的框的 id(很重要,因此我們可以跟蹤我們考慮過的框), qty
總結了容器中當前所有盒子的大小, lvl
顯示了容器中有多少盒子。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.