SQL 語法取得品號庫存各批號進出的剩餘數量

一般的資料表會逐一記錄品號及每一個批號進出倉庫數量,以便日後計算該品號及各批號的結餘數量,可以使用下面的SQL指令來取得匯總的資料

SQL
SELECT
    MF001 AS 品號,
    MF002 AS 批號,
    MF008 AS 進出,
    -- 計算數量的淨額
    SUM(數量 * MF008) AS Net_Quantity,
    -- 計算包裝數量的淨額
    SUM(包裝數量 * MF008) AS Net_Package_Quantity
FROM
    YourTableName
GROUP BY
    MF001,
    MF002;

取得的資料如下

image

使用 UNION ALL 的方法

可以透過下列步驟來計算出品號及各批號的結餘數量

SQL
-- 步驟 1 & 2: 獨立查詢與調整
(SELECT MF001, MF002, 數量 AS Qty, 包裝數量 AS Pkg_Qty FROM YourTable WHERE MF008 = 1)
UNION ALL
(SELECT MF001, MF002, -數量 AS Qty, -包裝數量 AS Pkg_Qty FROM YourTable WHERE MF008 = -1)

-- 步驟 3: 對 UNION ALL 結果進行彙總
SELECT MF001, MF002, SUM(Qty) AS Net_Quantity, SUM(Pkg_Qty) AS Net_Package_Quantity
FROM ( [上述 UNION ALL 結果] ) AS CombinedData
GROUP BY MF001, MF002;

整個的SQL語法如下

SQL
SELECT MF001, MF002, SUM(Qty) AS Net_Quantity, SUM(Pkg_Qty) AS Net_Package_Quantity
FROM ( 
	(SELECT MF001, MF002, 數量 AS Qty, 包裝數量 AS Pkg_Qty FROM YourTable WHERE MF008 = 1)
	UNION ALL
	(SELECT MF001, MF002, -數量 AS Qty, -包裝數量 AS Pkg_Qty FROM YourTable WHERE MF008 = -1)
) AS CombinedData
GROUP BY MF001, MF002;

儘管此方法在功能上是正確的,但從架構角度來看是存在嚴重缺陷的,尤其不適合高吞吐量或大資料集。使用 UNIONALL 會從根本上破壞直接乘法器方法的單次掃描效率 。

這種架構的效能缺陷源於資料庫必須執行的 I/O 耗能。每個 UNIONALL 中的 SELECT 語句通常都需要對基礎資料表或相關索引進行一次獨立的讀取或掃描。這意味著,為了獲取完整的資料集,資料庫可能需要執行兩次甚至更多的全表掃描。隨後,DBMS 必須將這些獨立的結果集合併起來,這通常需要在記憶體中或磁碟上使用暫存空間進行合併(Merge)或排序(Sort)操作,然後才能進行最終的外部 GROUPBY 彙總。

這種多重 I/O 和額外的資料處理步驟導致整體延遲顯著增加,使 UNIONALL 方法成為處理交易淨額核對任務時,應被避免的次優選擇。

使用 CASE WHEN 的方法

case when 可以優化計算出品號及各批號的結餘數量

SQL
SELECT MF001, MF002
	,sum( case when MF008=1  then MF010 else -MF010 end ) AS Net_Quantity 
	,sum( case when MF008=1  then MF014 else -MF014 end ) AS Net_Package_Quantity
FROM YourTable
GROUP BY MF001,MF002
ORDER BY MF001,MF002;

功能上,此 CASE 語句的方法產生在現代資料庫系統中,通常能將這種簡單的二元 CASE 邏輯優化到與乘法操作幾乎相同的執行成本。使用 CASE 語句才可能在語義上提供更清晰的表達。對於當前僅有 1 和 −1 的簡單二元邏輯,直接乘法更簡潔、更優雅,通常在執行計畫上負擔較輕。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *


內容索引