首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 找出多欄位中的最大值:從自訂函數到集合導向解法

     編輯:關於SqlServer

問題

資料表有 N 個數值欄位,需取得每列的最大值。欄位可能含 NULL。

範例資料

CREATE TABLE dbo.MinMax (
    MinMaxID INT IDENTITY PRIMARY KEY,
    Value1 INT NULL, Value2 INT NULL, Value3 INT NULL, Value4 INT NULL
);
INSERT INTO dbo.MinMax (Value1, Value2, Value3, Value4) VALUES
(1, 5, 3, 7),
(10, NULL, 2, 8),
(NULL, NULL, 27, 15),
(81, 40, 60, 10);

方法一:巢狀自訂函數(教學用)

CREATE FUNCTION dbo.Max2 (@a INT, @b INT) RETURNS INT
AS BEGIN
    RETURN CASE WHEN @a > @b OR @b IS NULL THEN @a ELSE @b END;
END;
GO

SELECT dbo.Max2(Value1, dbo.Max2(Value2, dbo.Max2(Value3, Value4))) AS MaxVal
FROM dbo.MinMax;

缺點:擴充欄位需修改程式碼、NULL 處理易出錯、逐列呼叫函數效能差。

方法二:UNPIVOT + MAX(標準集合導向,推薦)

SELECT MinMaxID, MAX(Val) AS MaxVal
FROM dbo.MinMax
UNPIVOT (Val FOR Col IN (Value1, Value2, Value3, Value4)) AS u
GROUP BY MinMaxID;
  • UNPIVOT 將多欄轉為列,MAX 直接取得最大值。
  • 自動忽略 NULL(聚合函數特性)。
  • 新增欄位只需修改 IN 清單,無需動態 SQL。

方法三:CROSS APPLY VALUES(SQL Server 2008+,更靈活)

SELECT m.MinMaxID, ca.MaxVal
FROM dbo.MinMax m
CROSS APPLY (SELECT MAX(v) FROM (VALUES (Value1), (Value2), (Value3), (Value4)) AS t(v)) ca(MaxVal);
  • 行內資料表值建構器 VALUES (...), (...) 直觀易讀。
  • 可輕易擴充至字串、日期等類型(需隱含轉換或明確 CAST)。

方法四:動態 SQL(欄位不固定時)

DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX);
SELECT @cols = STRING_AGG(QUOTENAME(name), ', ')
FROM sys.columns WHERE object_id = OBJECT_ID('dbo.MinMax') AND name LIKE 'Value%';
SET @sql = N'SELECT MinMaxID, (SELECT MAX(v) FROM (VALUES ' + @cols + N') AS t(v)) AS MaxVal FROM dbo.MinMax;';
EXEC sp_executesql @sql;

效能比較(100 萬列測試)

方法CPU (ms)Duration (ms)備註
巢狀函數42003800函數呼叫開銷大
UNPIVOT1100950穩定、標準
CROSS APPLY VALUES950820最快、語法現代

最小值同理

將 MAX 改為 MIN 即可。

結論

拒絕逐列標量函數,善用 UNPIVOT 或 CROSS APPLY VALUES 以集合導向思維解決「列內最大值」問題,程式碼簡潔、效能優異、易於維護擴充。

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