首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

SQL 多表合並統計:出入庫表生成匯總報表的標準寫法

     編輯:程式設計綜合問答

需求

出庫表 (產品名稱, 出庫數量, 出庫時間) + 入庫表 (產品名稱, 入庫數量, 入庫時間) → 指定時間段內每產品入庫總量、出庫總量。

標準解法:全外連接 + 條件聚合

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 產品名稱;

SQL Server 兼容寫法 (無 FULL JOIN 時)

-- 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,效能穩健。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved