【Linq】 左连接、右连接、内连接、交叉连接、 自连接以及效率对比
执行内部联接
在关系数据库术语中,内部联接会生成一个结果集,在该结果集中,第一个集合的每个元素对于第二个集合中的每个匹配元素都会出现一次。 如果第一个集合中的元素没有匹配元素,则它不会出现在结果集中。 由 C# 中的 join
子句调用的 Join 方法可实现内部联接。
本文演示如何执行内联的四种变体:
-
基于简单键使两个数据源中的元素相关联的简单内部联接。
-
基于复合键使两个数据源中的元素相关联的内部联接。 复合键是由多个值组成的键,使你可以基于多个属性使元素相关联。
-
在其中将连续联接操作相互追加的多联接。
-
使用分组联接实现的内部联接。
案例如下:
https://learn.microsoft.com/zh-cn/dotnet/csharp/linq/perform-left-outer-joins
左外部联接
stocksinfo表格--A表格
packetassociationstocks 表格--B表格
实现 stocksinfo表格 和packetassociationstocks 表格 的左外连接,并且选择 Join后的前10条记录
/// <summary> /// 为指定的板块添加股票 /// </summary> /// <param name="blockID">板块id</param> /// <param name="keyword">查找关键词</param> /// <returns></returns> public async Task<ObservableCollection<StockPOCO>?> GetStocksForPacketAsync(int blockID,string keyword) { ObservableCollection<StockPOCO>? coll = new(); //选取股票名称或者名字 保护指定关键词的 选取前十条记录 var content = (from A in dataContext.Stocksinfos join B in dataContext.Packetassociationstocks on A.Stockid equals B.Stockid into prodGroupList from C in prodGroupList.DefaultIfEmpty()//DefaultIfEmpty()实现左外连接 where A.Stockid.Contains(keyword) || A.Name.Contains(keyword)// 筛选 表格A,切记不是筛选prodGroupList select new StockPOCO{ StockID= A.Stockid, Name= A.Name, HadAdded= C.Isselected==1 } ).Take(10).ToList(); return new ObservableCollection<StockPOCO>(content); }
解说:
第一步、使用分组联接执行内联。
在关系数据库术语中,内部联接会生成一个结果集,在该结果集中,第一个集合的每个元素对于第二个集合中的每个匹配元素都会出现一次。 如果第一个集合中的元素没有匹配元素,则它不会出现在结果集中。
分组联接会创建中间组的集合,其中每个组都包含 Stocksinfos对象和匹配 Packetassociationstocks对象的序列。
第二步、在结果集内包含第一个(左)集合的每个元素,即使该元素在右集合中没有匹配的元素也是如此。 这是通过对分组联接中的每个匹配元素序列调用 DefaultIfEmpty 来实现的。
重点就是into到集合,再DefaultIfEmpty()
右外部联接
stocksinfo表格--A表格
packetassociationstocks 表格--B表格
实现 stocksinfo表格 和packetassociationstocks 表格 的右外连接,和左外连接就是from的对象换了一下
/// <summary> /// 根据指定的板块id 选择所有股票 /// </summary> /// <param name="PacketId">板块id</param> /// <returns></returns> public ObservableCollection<StockPOCO>? GetALLByPacketId(int PacketId) { ObservableCollection<StockPOCO>? coll = new(); var content = (from B in dataContext.Packetassociationstocks join A in dataContext.Stocksinfos on B.Stockid equals A.Stockid into prodGroupList from C in prodGroupList.DefaultIfEmpty()//DefaultIfEmpty()实现左外连接 where B.Packetid== PacketId // 筛选 表格B,切记不是筛选prodGroupList select new StockPOCO { StockID = B.Stockid, Name =C.Name, HadAdded = B.Isselected == 1 } ).ToList(); return new ObservableCollection<StockPOCO>(content); }
交叉连接
自连接
自连接作为一种特例,可以将一个表与它自身进行连接,称为自连接。
若要在一个表中查找具有相同列值的行,则可以使用自连接。
使用自连接时需为表指定两个别名,且对所有列的引用均要用别名限定。
SELECT a.学号, a.课程号, b.课程号, a.成绩 FROM student a JOIN student b ON a.成绩=b.成绩 AND a.学号=b.学号 AND a.课程号!=b.课程号
等值连接和自然连接的区别:
-
等值连接中不要求相等属性值的属性名相同,而自然连接要求相等属性值的属性名必须相同,即两关系只有在同名属性才能进行自然连接。
-
等值连接不将重复属性去掉,而自然连接去掉重复属性,也可以说,自然连接是去掉重复列的等值连接。
效率对比
外连接在步骤上是比内连接多出一步的
从下图的解析上可以看出这个是mysql执行的时候执行顺序可以看出外连接是比内连接多出了一步操作。
但是具体效率并没有多少区分还是由语句决定大部分的执行效率。
而且左连接语句有时候会被数据库优化器自动转化为内连接,所以该语句优化器判断为合适执行内连接并且效率高。
在这里插入图片描述
2.左连接的时候以左表为原则,根据左表查询, 并且会进行回表操作,当左表数据量比较大,就需要更多的时间,展示左表中的元素,其他的表字段为空一样展示。
3.内连接,查询出交集,展示他们相同的元素。
总结:
1.先看公司的需求,再进行选择左连接还是内连接
2.在选择左连接还是内连接都没有问题的情况下,就选择内连接