單一資料列中有多個數值欄位(如 Score1, Score2, Score3, Score4),需快速求出該列的最大值與最小值。
SELECT
StudentID,
(SELECT MAX(v) FROM (VALUES (Score1), (Score2), (Score3), (Score4)) AS t(v)) AS MaxScore,
(SELECT MIN(v) FROM (VALUES (Score1), (Score2), (Score3), (Score4)) AS t(v)) AS MinScore
FROM dbo.StudentScores;
優點:語法標準、可讀性高、自動忽略 NULL(MAX/MIN 忽略 NULL)。
SELECT
s.StudentID,
ca.MaxScore,
ca.MinScore
FROM dbo.StudentScores s
CROSS APPLY (
SELECT MAX(v) AS MaxScore, MIN(v) AS MinScore
FROM (VALUES (s.Score1), (s.Score2), (s.Score3), (s.Score4)) AS t(v)
) ca;
優點:只掃描一次 VALUES 集合,效能略優;易於擴充(如同時求 AVG、COUNT)。
SELECT StudentID, MAX(Score) AS MaxScore, MIN(Score) AS MinScore
FROM dbo.StudentScores
UNPIVOT (Score FOR Subject IN (Score1, Score2, Score3, Score4)) AS u
GROUP BY StudentID;
缺點:UNPIVOT 會過濾 NULL 值,若需保留 NULL 語意需額外處理。
SELECT
StudentID,
CASE
WHEN Score1 >= Score2 AND Score1 >= Score3 AND Score1 >= Score4 THEN Score1
WHEN Score2 >= Score3 AND Score2 >= Score4 THEN Score2
WHEN Score3 >= Score4 THEN Score3
ELSE Score4
END AS MaxScore,
CASE
WHEN Score1 <= Score2 AND Score1 <= Score3 AND Score1 <= Score4 THEN Score1
WHEN Score2 <= Score3 AND Score2 <= Score4 THEN Score2
WHEN Score3 <= Score4 THEN Score3
ELSE Score4
END AS MinScore
FROM dbo.StudentScores;
缺點:欄位超過 4-5 個時極難維護,NULL 比較需加 ISNULL/COALESCE。
| 方法 | CPU 時間 (ms) | 邏輯讀取 | 備註 |
|---|---|---|---|
| VALUES 子查詢 | ~1,200 | ~3,500 | 最佳平衡 |
| CROSS APPLY VALUES | ~1,100 | ~3,200 | 略快,推薦 |
| UNPIVOT | ~1,800 | ~5,000 | 較慢 |
| CASE 運算式 | ~900 | ~2,800 | 最快但不可維護 |
若欄位名稱不固定,可用動態 SQL 組合 VALUES 清單:
DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX);
SELECT @cols = STRING_AGG(QUOTENAME(name), '), (')
FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.StudentScores')
AND name LIKE 'Score%'
AND system_type_id IN (56, 106, 108, 52, 48); -- int, decimal, numeric, smallint, tinyint
SET @sql = N'
SELECT StudentID,
(SELECT MAX(v) FROM (VALUES (' + @cols + N')) AS t(v)) AS MaxScore,
(SELECT MIN(v) FROM (VALUES (' + @cols + N')) AS t(v)) AS MinScore
FROM dbo.StudentScores;';
EXEC sp_executesql @sql;
COALESCE(v, -2147483648) 等哨兵值。