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

LINQ 學習筆記:聚合方法完整指南 (Count, Min, Max, Sum, Average, Aggregate)

     編輯:關於SqlServer

LINQ 提供豐富的聚合運算子,對應 SQL 聚合函數,支援記憶體集合 (LINQ to Objects) 與資料庫查詢 (LINQ to SQL) 雙重場景。本文系統整理六大核心方法語法、行為差異與進階用法。

核心聚合方法對照表

方法SQL 對應回傳型別說明
Count / LongCountCOUNT(*)int / long元素總數或符合條件數量
Min / MaxMIN() / MAX()TSource / TResult最小/最大值,支援選擇器投影
Sum / AverageSUM() / AVG()數值型別 (decimal/double)總和/平均,需數值型別
Aggregate無直接對應TAccumulate / TResult自訂累積演算法 (LINQ to SQL 不支援)

Count / LongCount


// 基本計數
int[] nums = { 5, 6, 7 };
int cnt = nums.Count(); // 3

// 帶斷言計數
string s = "jame921";
int digitCnt = s.Count(c => char.IsDigit(c)); // 3

// LongCount:相同功能,回傳 long,適用 > 20 億元素集合
long bigCnt = largeCollection.LongCount();

實作細節: Count() 內部優先檢查 ICollection<T> 介面,若實作則直接讀取 Count 屬性 (O(1)),否則逐一枚舉計數 (O(N))。

Min / Max


int[] numbers = { 28, 32, 14 };
int min = numbers.Min(); // 14
int max = numbers.Max(); // 32

// 選擇器投影:比較個位數
int minDigit = numbers.Min(n => n % 10); // 2 (14%10=4, 28%10=8, 32%10=2) → 2
int maxDigit = numbers.Max(n => n % 10); // 8

// 複雜型別必須提供選擇器 (未實作 IComparable)
var cheapestPrice = ctx.Purchases.Min(p => p.Price); // OK: decimal?
// var cheapestOrder = ctx.Purchases.Min(); // 編譯錯誤:Purchase 無 IComparable

// 取得最便宜訂單完整物件:需子查詢
var cheapestOrder = ctx.Purchases
    .Where(p => p.Price == ctx.Purchases.Min(p2 => p2.Price))
    .FirstOrDefault();

Sum / Average


decimal[] vals = { 3, 4, 8 };
decimal sum = vals.Sum(); // 15
decimal avg = vals.Average(); // 5

// 選擇器:字串長度總和
string[] names = { "Tom", "Jerry" };
int totalLen = names.Sum(s => s.Length); // 3+5=8

// 型別規則嚴格:
// - Sum/Average 僅支援數值型別 (int, long, float, double, decimal 及其 nullable)
// - Min/Max 支援任何實作 IComparable 的型別 (含 string)

// Average 回傳型別規則:
// 1. 選擇器為 decimal → 回傳 decimal
// 2. 選擇器為 int/long/float/double → 回傳 double
// 因此:
// int avg = new int[]{3,4}.Average(); // 編譯錯誤:double 無法隱含轉換 int
double avg = new int[]{3,4}.Average(); // 3.5 ✓

// 精度提升:Average 內部以 double/decimal 累加避免溢位/精度損失
double avg2 = numbers.Average(n => (double)n); // 同結果

LINQ to SQL 翻譯範例


// 找出平均訂單金額 > 500 的客戶名稱
var q = from c in ctx.Customers
        where c.Purchases.Average(p => p.Price) > 500
        select c.Name;
// 翻譯為 SQL:AVG(Price) 配合 GROUP BY / HAVING

Aggregate:自訂聚合演算法

適用於 LINQ to Objects (記憶體集合) 的複雜累積邏輯,**LINQ to SQL 不支援** (無法翻譯為 SQL)。


// 等同於 Sum 的自訂實現
int[] numbers = { 1, 2, 3 };
int sum = numbers.Aggregate(0, (seed, n) => seed + n); // 6

// 參數解析:
// 1. seed (種子/初始值) = 0
// 2. func (累積函數) = (目前累積值, 下一個元素) => 新累積值
// 3. 可選第三參數 resultSelector:最終投影

// 進階:計算標準差 (兩次遍歷或單次雙累積)
double mean = numbers.Average();
double stdDev = Math.Sqrt(numbers.Average(x => Math.Pow(x - mean, 2)));

總結:選擇指南

  • 簡單計數/極值/總和/平均 → 直接使用對應方法,可讀性最佳。
  • 需自訂邏輯 (如標準差、中位數、字串連接) → Aggregate (僅 LINQ to Objects)。
  • 資料庫查詢 → 優先使用標準方法 (可翻譯 SQL),避免 Aggregate 導致客戶端評估效能災難。
  • 型別安全:Average 回傳 double/decimal,切勿隱含轉換為 int。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved