出庫表 (產品名稱, 出庫數量, 出庫時間) + 入庫表 (產品名稱, 入庫數量, 入庫時間) → 指定時間段內每產品入庫總量、出庫總量。
SELECT
COALESCE(i.產品名稱, o.產品名稱) AS 產品名稱,
ISNULL(i.入庫總量, 0) AS 入庫總量,
ISNULL(o.出庫總量, 0) AS 出庫總量
FROM (
SELECT 產品名稱, SUM(入庫數量) AS 入庫總量
FROM 入庫表
WHERE 入庫時間 BETWEEN @開始時間 AND @結束時間
GROUP BY 產品名稱
) i
FULL OUTER JOIN (
SELECT 產品名稱, SUM(出庫數量) AS 出庫總量
FROM 出庫表
WHERE 出庫時間 BETWEEN @開始時間 AND @結束時間
GROUP BY 產品名稱
) o ON i.產品名稱 = o.產品名稱
ORDER BY 產品名稱;
-- 1. 獲取所有產品名稱
SELECT 產品名稱 FROM 入庫表 WHERE 入庫時間 BETWEEN @s AND @e
UNION
SELECT 產品名稱 FROM 出庫表 WHERE 出庫時間 BETWEEN @s AND @e
-- 2. 左連接聚合子查詢
SELECT t.產品名稱,
ISNULL(i.入庫總量, 0) AS 入庫總量,
ISNULL(o.出庫總量, 0) AS 出庫總量
FROM (
SELECT 產品名稱 FROM 入庫表 WHERE 入庫時間 BETWEEN @s AND @e
UNION
SELECT 產品名稱 FROM 出庫表 WHERE 出庫時間 BETWEEN @s AND @e
) t
LEFT JOIN (
SELECT 產品名稱, SUM(入庫數量) AS 入庫總量
FROM 入庫表 WHERE 入庫時間 BETWEEN @s AND @e
GROUP BY 產品名稱
) i ON t.產品名稱 = i.產品名稱
LEFT JOIN (
SELECT 產品名稱, SUM(出庫數量) AS 出庫總量
FROM 出庫表 WHERE 出庫時間 BETWEEN @s AND @e
GROUP BY 產品名稱
) o ON t.產品名稱 = o.產品名稱;
| 技術點 | 作用 |
|---|---|
| UNION 去重 | 獲取兩表所有不重複產品名稱,作為主表 |
| 子查詢預聚合 | 先分組求和再連接,避免笛卡爾積膨脹 |
| LEFT JOIN + ISNULL | 保留無出入庫記錄的產品,缺失補 0 |
| BETWEEN 含邊界 | 時間範圍過濾推下推到子查詢,利用索引 |
CREATE INDEX IX_入庫_時間_產品 ON 入庫表(入庫時間, 產品名稱) INCLUDE (入庫數量);
CREATE INDEX IX_出庫_時間_產品 ON 出庫表(出庫時間, 產品名稱) INCLUDE (出庫數量);
此寫法兼容 SQL Server / MySQL / PostgreSQL / Oracle,效能穩健。