LINQ學習筆記(7)實作Left join(1) Join與Group join

莊創偉
5 min readNov 14, 2017

LINQ中的Join對應T-SQL中的 inner join, 並無Left Join的方法,當然也沒有Right Join。

要達成Left join 必須依靠GroupJoin來完成。

GroupJoin 顧名思義就是先Group 在做 Join ,與Join的不同處在於Join會得到一個一對一的新物件集合 (List<T>),而GroupJoin 則會得到一對多的物件集合({key,List<T>})。

以下是join 與GroupJoin的比較

資料表如圖:ID=004無可對應的資料
var _Join = SLIST.Join(ScoreList, o => o.ID, p => p.StudentID, (o, c) => new { o.Classroom, o.ID,o.Name, c.Class,c.score });
ID=004 不會在結果集合中
var _GroupJoin = SLIST.GroupJoin(ScoreList, o => o.ID, p => p.StudentID, (o, c) => new { o.Classroom, o.ID, c });
//c只能以泛型物件的方式存入,不能列舉屬性
物件c會比對key值各自存入

可以看GroupJoin 可以得到與Left Join相似的結果

接下來只要使用 SelectMany 將GroupJoin 中的內容展開

//將矩陣展開並輸出Null 得到left join資料集var _GroupJoinToLeftJoin = SLIST.GroupJoin(ScoreList, o => o.ID, p => p.StudentID, (o, c) => new { o.Classroom, o.ID,o.Name, c }).SelectMany(o => o.c.DefaultIfEmpty(), (o, c) => new { o.ID, o.Classroom,o.Name,Class=(c==null||c.Class==null?"N/A":c.Class), score= (c == null || c.score == null ? new Nullable<ushort>() : c.score) });//SelectMany 展開矩陣的內容//使用DefaultIfEmpty 因匿名型別無法輸出NULL(無法轉換成強型別),需特別注意Null的處理
得到符合預期的Left Join結果

查詢式的表示方法會比Lambda來的簡單一點

//查詢示 GroupJoin 寫法var _GroupJointoSQl=from o in SLISTjoin p in ScoreListon o.ID equals p.StudentIDinto groupjoin select groupjoin;//into 就是方法式中的 groupjoin

Left Join

var _LeftJointoSQl=from o in SLIST
join p in ScoreList
on o.ID equals p.StudentID
into groupjoin from a in groupjoin.DefaultIfEmpty()
select new{ o.ID, o.Classroom,o.Name,Class=(a==null||a.Class==null?"N/A":a.Class),
score= (a == null || a.score == null ? new Nullable<ushort>() : a.score)};

但是需注意,如果用 where 的方式做 join 的話會無法調用 DefaultIfEmpty()的方法

var Error = from o in SLISTfrom p in ScoreListwhere o.ID == p.StudentIDselect new { o.ID, o.Classroom, o.Name, p.Class, p.score }into sGroup from s in sGroup.DefaultIfEmpty()  select sGroup;

因為使用where 後面必須接Select 語句輸出,但是select 後會成為匿名型別,無法再調用DefaultIfEmpty()

--

--

莊創偉

學海無涯。但是為了生計還是得下海的風塵男子