承接上篇,本文提供完整 T-SQL 程式碼範例,詳細展示各優化技巧的實作細節與效能比較。
CREATE TRIGGER trProducts_Insert ON Products FOR INSERT AS
SELECT @@IDENTITY
GO
觸發器僅在 Products 表發生 INSERT 時啟動,確保每次成功插入皆自動回傳新身分識別值,應用程式端呼叫方式統一。
CREATE TABLE #Temp1 (OrderID INT NOT NULL, OrderDate DATETIME NOT NULL);
INSERT INTO #Temp1 SELECT TOP 5 OrderID, OrderDate FROM Orders ORDER BY OrderDate DESC;
SELECT p.ProductName, SUM(od.Quantity) AS ProductQuantity
FROM #Temp1 t
INNER JOIN [Order Details] od ON t.OrderID = od.OrderID
INNER JOIN Products p ON od.ProductID = p.ProductID
GROUP BY p.ProductName ORDER BY p.ProductName;
DROP TABLE #Temp1;
SELECT p.ProductName, SUM(od.Quantity) AS ProductQuantity
FROM (SELECT TOP 5 OrderID, OrderDate FROM Orders ORDER BY OrderDate DESC) t
INNER JOIN [Order Details] od ON t.OrderID = od.OrderID
INNER JOIN Products p ON od.ProductID = p.ProductID
GROUP BY p.ProductName ORDER BY p.ProductName;
內嵌檢視表避免 tempdb 大量讀寫,資源消耗顯著降低。
若 Products 表的 CategoryID 允許 NULL,查詢所有產品含分類需 LEFT JOIN。改為建立「無分類」預設分類 (CategoryID = 999),外鍵設 NOT NULL,即可改用 INNER JOIN:
-- 修改前
SELECT p.ProductName, c.CategoryName
FROM Products p LEFT JOIN Categories c ON p.CategoryID = c.CategoryID;
-- 修改後 (需資料庫設計配合)
SELECT p.ProductName, c.CategoryName
FROM Products p INNER JOIN Categories c ON p.CategoryID = c.CategoryID;
此設計消除資源密集型 LEFT JOIN,對高併發系統效能提升顯著。
需求:列出過去 12 個月每位客戶的銷售額,含零銷售月份。
DECLARE @tblMonths TABLE (sMonth VARCHAR(7));
DECLARE @i INT = 0, @dtEndDate DATETIME = '1997-05-05', @dtDate DATETIME;
SET @dtEndDate = DATEADD(DD, -1, CAST(CAST(MONTH(@dtEndDate)+1 AS VARCHAR(2)) + '/01/' + CAST(YEAR(@dtEndDate) AS VARCHAR(4)) + ' 23:59:59' AS DATETIME));
SET @dtStartDate = DATEADD(MM, -12, @dtEndDate);
WHILE @i < 12 BEGIN
SET @dtDate = DATEADD(MM, -@i, @dtEndDate);
INSERT @tblMonths SELECT CAST(YEAR(@dtDate) AS VARCHAR(4)) + '-' + RIGHT('0'+CAST(MONTH(@dtDate) AS VARCHAR(2)),2);
SET @i = @i + 1;
END
DECLARE @tblCustomers TABLE (CustomerID CHAR(10), CompanyName VARCHAR(50), ContactName VARCHAR(50));
INSERT @tblCustomers SELECT DISTINCT c.CustomerID, c.CompanyName, c.ContactName
FROM Customers c INNER JOIN Orders o ON c.CustomerID = o.CustomerID
WHERE o.OrderDate BETWEEN @dtStartDate AND @dtEndDate;
DECLARE @tblFinal TABLE (sMonth VARCHAR(7), CustomerID CHAR(10), CompanyName VARCHAR(50), ContactName VARCHAR(50), mSales MONEY);
INSERT @tblFinal SELECT m.sMonth, c.CustomerID, c.CompanyName, c.ContactName, 0
FROM @tblMonths m CROSS JOIN @tblCustomers c;
UPDATE f SET mSales = mydata.mSales
FROM @tblFinal f
INNER JOIN (
SELECT c.CustomerID,
CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' + RIGHT('0'+CAST(MONTH(o.OrderDate) AS VARCHAR(2)),2) AS sMonth,
SUM(od.Quantity * od.UnitPrice) AS mSales
FROM Customers c
INNER JOIN Orders o ON c.CustomerID = o.CustomerID
INNER JOIN [Order Details] od ON o.OrderID = od.OrderID
WHERE o.OrderDate BETWEEN @dtStartDate AND @dtEndDate
GROUP BY c.CustomerID, CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' + RIGHT('0'+CAST(MONTH(o.OrderDate) AS VARCHAR(2)),2)
) mydata ON f.CustomerID = mydata.CustomerID AND f.sMonth = mydata.sMonth;
SELECT * FROM @tblFinal ORDER BY CompanyName, sMonth;
此法一次產生 12個月 × 81客戶 = 972 列完整矩陣,完美解決報表零值顯示問題。
DISTINCT 純增開銷。優化無捷徑,唯有持續測試、分析執行計畫、比較不同寫法,才能找出最適合特定業務場景的最佳方案。