2016-08-01 59 views
0

SQL初學者在這裏。用SQL查詢分割訂單

因爲我的問題是有點難以解釋,我會嘗試用Excel來說明吧:

enter image description here

有一些供應商,每個誰提供一定的權重不同的供應商號碼。 由於一輛卡車只能運輸24噸,我想有表 的價值分割的價值爲24. 因此,30噸將意味着2噸不同的訂單之一與24噸,一噸與6噸。

有沒有什麼方法可以解決SQL查詢問題?

感謝您的幫助!使用遞歸因式分解子查詢

+0

難道你不只是有一個計算,做TON_WEIGHT/24,並將其存儲在表的一列中?爲什麼你需要知道一輛卡車需要24和其他需求6,而不是它將存儲1.25,你會知道這個訂單需要1和25卡車採取這個訂單。本來意味着1輛卡車意味着全部24和25卡車意味着6?選擇噸/ 30 AS TrucksNeeded從TABLENAME; –

+0

SELECT Tons/30 AS TrucksNeeded FROM TABLENAME;這可以給你結果,你也可以把這個結果放到你已有的表中,如果你覺得這個表需要這個信息,那麼你可能在表中添加一列的另一個原因是計算昂貴,不想一遍又一遍地做,但在這種情況下,簡單的劃分就沒有問題。 –

+0

也可以將它看作44.6這樣的數字,因爲這個訂單需要45輛卡車,所以這個數字會被讀取。 44將會完成,下一輛卡車將會滿載。還有,你可以使用這個數字,比如44.6來計算一個總成本可以說它是每輛卡車15美元,所以44.6 * 15,這是另一個簡單的計算和查詢 –

回答

1

你可以使用recursive subquery factoring(假設你在11gR2中或更高版本):

with r (supplier_number, order_weight, truck_number, truck_weight, remaining_weight) as (
    select supplier_number, order_weight, 1, 
    least(order_weight, 24), order_weight - 24 
    from t 
    union all 
    select supplier_number, order_weight, truck_number + 1, 
    least(remaining_weight, 24), remaining_weight - 24 
    from r 
    where remaining_weight > 0 
) 
select supplier_number, order_weight, truck_number, truck_weight 
from r 
order by supplier_number, truck_number; 

SUPPLIER_NUMBER ORDER_WEIGHT TRUCK_NUMBER TRUCK_WEIGHT 
--------------- ------------ ------------ ------------ 
       1   10   1   10 
       2   25   1   24 
       2   25   2   1 
       3   88   1   24 
       3   88   2   24 
       3   88   3   24 
       3   88   4   16 

錨構件得到原來的體重,或24,如果它高於這個數字,使用the least() function - 這就是卡車號碼1;並且還計算了剩餘的內容(這可能是負面的,因爲它沒有關係)。如果遞歸成員大於零,則遞歸成員重複計算上一級別的剩餘部分。

+0

感謝您的幫助!假設我的表由兩行supplier_numbers和order_weight組成(如我的示例中所示),並將表命名爲「t」,此方法將工作嗎?不幸的是,我現在無法對其進行測試,但我會在明天報告它的工作情況! – lexcro

+0

是的,我使用了一個名爲't'的CTE來提供您的樣本數據,並生成了我顯示的輸出結果;把't'改成你真正的表名。 –

+0

非常感謝!假設我想添加另一行,例如供應商的郵政編碼,我該怎麼做?由於我相當新的SQL,我沒有設法改變代碼沒有得到一個錯誤。 – lexcro

1

解決方案:

with 
    inputs (supplier_number, order_weight) as (
     select 1, 10 from dual union all 
     select 2, 25 from dual union all 
     select 3, 88 from dual 
    ), 
    r (supplier_number, shipment_number, order_weight, weight_remaining) as (
     select supplier_number, 0, null, order_weight 
     from inputs 
     union all 
     select supplier_number, shipment_number + 1, least(24, weight_remaining), 
       greatest(0, weight_remaining - 24) 
     from r 
     where weight_remaining != 0 
    ) 
select supplier_number, shipment_number, order_weight 
from  r 
where shipment_number > 0 
order by supplier_number, shipment_number 
; 




SUPPLIER_NUMBER SHIPMENT_NUMBER ORDER_WEIGHT 
--------------- --------------- ------------ 
       1    1   10 
       2    1   24 
       2    2   1 
       3    1   24 
       3    2   24 
       3    3   24 
       3    4   16 
1

你可以用數字表來做到這一點。讓我假設你有一個:

select t.*, n.n, 
     (case when n.n * 24 <= t.tons then 24 
      else mod(t.tons, 24) 
     end) 
from t join 
    numbers n 
    on (n.n - 1) * 24 < t.tons; 

這裏是生成一個數字表,如果你的表是足夠大,一個簡單的辦法:

with numbers as (
     select rownum as n 
     from t 
    ) 
+0

當t.tons被24整除時,這將不起作用。例如:t.tons = 24。連接條件將'n'限制爲1,這是正確的。但CASE表達式將返回0而不是24(1 * 24不是<24)。 (這很容易解決,將第一個<更改爲<=,但希望網站上的頂級專家更好......) – mathguy

+0

@mathguy。 。 。我很想念你的評論。如果噸數是24,那麼只應該生產一排。您的評論解釋了原因。 –

+0

正確,只會生成一行,但運送的重量(OP稱爲電子表格右側的「訂單重量」)應爲24.您的公式計算0; mod(24,24)= 0,而不是24。 – mathguy