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

LINQ 學習筆記:Join 與 GroupJoin 完整指南 (二) - GroupJoin 左外連接、扁平化 Outer Join、into 語法細節

     編輯:關於SqlServer

承接上篇,本文深入 GroupJoin 層級結果結構、into 關鍵字語義、預設左外連接行為、轉為內連接過濾、扁平化左外連接實作模式。

GroupJoin 基礎:層級結果結構


var q = from c in customers
        join p in purchases on c.ID equals p.CustomerID
        into custPurchases          // into 將右側群組引入作用域
        select custPurchases;       // 選擇群組本身

// 結果型別:IEnumerable>
// 列舉方式:
foreach (var purchaseSeq in q) {
    foreach (var p in purchaseSeq) Console.WriteLine(p.Description);
}

同時選擇外部元素與群組


// 保留客戶名稱與其訂單群組
var q = from c in customers
        join p in purchases on c.ID equals p.CustomerID
        into custPurchases
        select new { CustName = c.Name, custPurchases };
// c 仍在作用域內可被引用

等效替代:Select 子查詢 (效能較差)


var q = from c in customers
        select new {
            CustName = c.Name,
            custPurchases = purchases.Where(p => c.ID == p.CustomerID)
        };
// 邏輯相同,但無 Join 的雜湊查找優化 (本地查詢)

GroupJoin 預設 = 左外連接

  • 外部序列 (customers) **所有元素保留**,無對應內部元素者群組為空序列。
  • 若需**內連接語義** (僅保留有匹配者):**在群組上過濾** where custPurchases.Any()。

// 內連接語義
var inner = from c in customers
            join p in purchases on c.ID equals p.CustomerID
            into custPurchases
            where custPurchases.Any()
            select new { c.Name, Orders = custPurchases };

群組內元素過濾 vs 連接前過濾

  • into 後的 where 作用於**整個子序列** (群組層級)。
  • 若需過濾**個別內部元素** (如價格 > 1000 的訂單):**必須在連接前對內部序列過濾**。

// 正確:先過濾購買單再連接
var q = from c in customers
        join p in purchases.Where(p2 => p2.Price > 1000)
        on c.ID equals p.CustomerID
        into custPurchases
        select new { c.Name, HighValueOrders = custPurchases };

扁平化左外連接 (Flattened Left Outer Join)

需求:左外連接語義 + **扁平結果集** (非層級)。解法:GroupJoin → DefaultIfEmpty → SelectMany (查詢運算式第二個 from)。


var q = from c in customers
        join p in purchases on c.ID equals p.CustomerID
        into custPurchases
        from cp in custPurchases.DefaultIfEmpty()  // 空群組產生 null
        select new {
            CustName = c.Name,
            Price = cp == null ? (decimal?)null : cp.Price
        };
  • DefaultIfEmpty():空序列 → 單一 null 元素序列。
  • 第二個 from 編譯為 SelectMany,將群組展平合併。
  • 結果:每個客戶對應零或多筆扁平記錄,無訂單者 Price = null。

關鍵語法區分:into 的雙重身分

位置語義產生型別
join ... intoGroupJoin (群組連接)IEnumerable>
select/group ... into查詢延續 (引入新範圍變數)依後續子句
兩者皆「引入新查詢變數」,但前者建立群組結構,後者單純延續查詢管線,**極易混淆需精確辨識**。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved