先入先出(FIFO)的一種SQL語句查詢演算法
在論壇上幾次碰到過類似的於FIFO問題,故共享一個有些"惡搞"的演算法。
在很多情況下,需要對一些記錄,比如出入庫記錄,收付款記錄進行先入先出的匹配。一般來說普通做法是在某個物料出庫的時候通過程式來對比實現。但這種設計對業務要求比較嚴格。比如需要事先制定,退貨,紅衝的處理方式。在一些簡單的系統中可以直接採用查詢來實現。下面用個例子來說明。
兩個表
入表 tin(id,marno,qty) // id,主鍵,可視為批號 ; marno , 物料編號; qty數量
出表 tout(id,marno,qty)
記錄如下
tin
id |marno|qty
1 | A |10
2 | A |5
3 | B |20
4 | C |7
5 | A |15
6 | A |20
tout
id |marno|qty
1 | A |3
2 | A |2
3 | B |10
4 | A |1
5 | A |30
對照演算法
出庫 |對應入庫批號
id |marno|qty |id |數量|剩
1 | A |3 | 1 |10 |7
2 | A |2 | 1 |7 |5
3 | B |10 | 3 |20 |10
4 | A |1 | 1 |5 |4
5 | A |4 | 1 |4 |
5 | A |5 | 2 |5 |
5 | A |15 | 5 |15 |
5 | A |6 | 6 |20 |14
期望結果
出庫 |對應入庫批號
id |marno|qty |id
1 | A |3 | 1
2 | A |2 | 1
3 | B |10 | 3
4 | A |1 | 1
5 | A |4 | 1
5 | A |5 | 2
5 | A |15 | 5
5 | A |6 | 6
SQL 語句:
SELECT o.id,o.marno,
iif(i.accQty<o.accQty,i.accQty,o.accQty) - iif(i.paccQty>o.paccQty,i.paccQty,o.paccQty) AS ActualIssureQty4Batch,
i.id
FROM (
SELECT id, marno, qty,
val(dsum('qty','tin','marno="'&marno&'" and id<='&id)) AS accQty,
accQty-qty AS paccQty
FROM tin
) AS i INNER JOIN (
SELECT id, marno, qty,
val(dsum('qty','tout','marno="'&marno&'" and id<='&id)) AS accQty,
accQty-qty AS paccQty
FROM tout
) AS o ON i.marno=o.marno and i.accQty>o.paccQty and i.paccQty<o.accQty
order by o.id,i.id
當然,也可以在查詢中加上tin的價格等欄位以滿足實際的需求。
注意
這個方法,做為趣味在表中記錄不多的情況尚可一用,如果是大量記錄,則使用程式碼解決比較高效。