菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
83
0

Linq表连接大全(INNER JOIN、LEFT OUTER JOIN、RIGHT OUTER JOIN、FULL OUTER JOIN、CROSS JOIN)

原创
05/13 14:22
阅读数 68125

转载http://www.cnblogs.com/shenqiboy/p/3260105.html

我们知道在SQL中一共有五种JOIN操作:INNER JOIN、LEFT OUTER JOIN、RIGHT OUTER JOIN、FULL OUTER JOIN、CROSS JOIN

      

内连接、
Sql: SELECT [t0].[GroupName], [t1].[UserName] FROM [Group] AS [t0] INNER JOIN [User] AS [t1] ON ([t0].[Id]) = [t1].[GroupId] Linq to Sql: from g in Groups join u in Users on g.Id equals u.GroupId select new { GroupName=g.GroupName, UserName=u.UserName} Lambda: Groups.Join ( Users, g => (Int32?)(g.Id), u => u.GroupId, (g, u) => new { GroupName = g.GroupName, UserName = u.UserName } )
 

 

左连接、

Sql:
-- Region Parameters
DECLARE @p0 NVarChar(1000) = ''
-- EndRegion
SELECT [t0].[GroupName], 
    (CASE 
        WHEN [t2].[test] IS NULL THEN CONVERT(NVarChar(50),@p0)
        ELSE [t2].[UserName]
     END) AS [UserName]
FROM [Group] AS [t0]
LEFT OUTER JOIN (
    SELECT 1 AS [test], [t1].[UserName], [t1].[GroupId]
    FROM [User] AS [t1]
    ) AS [t2] ON ([t0].[Id]) = [t2].[GroupId]

Linq to Sql:
from g in Groups
join u in Users
on g.Id  equals u.GroupId
into Grp
from grp in Grp.DefaultIfEmpty()
select new { GroupName=g.GroupName, UserName=(grp==null)?"":grp.UserName}

Lambda:
Groups.GroupJoin (
      Users, 
      g => (Int32?)(g.Id), 
      u => u.GroupId, 
      (g, Grp) => 
         new  
         {
            g = g, 
            Grp = Grp
         }
   ) .SelectMany (
      temp0 => temp0.Grp.DefaultIfEmpty (), 
      (temp0, grp) => 
         new  
         {
            GroupName = temp0.g.GroupName, 
            UserName = (grp == null) ? "" : grp.UserName
         }
   )

右连接、

Sql:
-- Region Parameters
DECLARE @p0 NVarChar(1000) = ''
-- EndRegion
SELECT 
    (CASE 
        WHEN [t2].[test] IS NULL THEN CONVERT(NVarChar(50),@p0)
        ELSE [t2].[GroupName]
     END) AS [GroupName], [t0].[UserName]
FROM [User] AS [t0]
LEFT OUTER JOIN (
    SELECT 1 AS [test], [t1].[Id], [t1].[GroupName]
    FROM [Group] AS [t1]
    ) AS [t2] ON [t0].[GroupId] = ([t2].[Id])

Linq to Sql:
from u in Users
join g in Groups
on u.GroupId equals g.Id
into Grp
from grp in Grp.DefaultIfEmpty()
select new { GroupName=(grp==null)?"":grp.GroupName, UserName=u.UserName}

Lambda:
Users.GroupJoin (
      Groups, 
      u => u.GroupId, 
      g => (Int32?)(g.Id), 
      (u, Grp) => 
         new  
         {
            u = u, 
            Grp = Grp
         }
   ).SelectMany (
      temp0 => temp0.Grp.DefaultIfEmpty (), 
      (temp0, grp) => 
         new  
         {
            GroupName = (grp == null) ? "" : grp.GroupName, 
            UserName = temp0.u.UserName
         }
   )

 

全连接、

Sql:
-- Region Parameters
DECLARE @p0 NVarChar(1000) = ''
DECLARE @p1 NVarChar(1000) = ''
-- EndRegion
SELECT DISTINCT [t7].[GroupName], [t7].[value] AS [UserName]
FROM (
    SELECT [t6].[GroupName], [t6].[value]
    FROM (
        SELECT [t0].[GroupName], 
            (CASE 
                WHEN [t2].[test] IS NULL THEN CONVERT(NVarChar(50),@p0)
                ELSE [t2].[UserName]
             END) AS [value]
        FROM [Group] AS [t0]
        LEFT OUTER JOIN (
            SELECT 1 AS [test], [t1].[UserName], [t1].[GroupId]
            FROM [User] AS [t1]
            ) AS [t2] ON ([t0].[Id]) = [t2].[GroupId]
        UNION ALL
        SELECT 
            (CASE 
                WHEN [t5].[test] IS NULL THEN CONVERT(NVarChar(50),@p1)
                ELSE [t5].[GroupName]
             END) AS [value], [t3].[UserName]
        FROM [User] AS [t3]
        LEFT OUTER JOIN (
            SELECT 1 AS [test], [t4].[Id], [t4].[GroupName]
            FROM [Group] AS [t4]
            ) AS [t5] ON [t3].[GroupId] = ([t5].[Id])
        ) AS [t6]
    ) AS [t7]

Linq to Sql:
var a=from g in Groups
join u in Users
on g.Id  equals u.GroupId
into Grp
from grp in Grp.DefaultIfEmpty()
select new { GroupName=g.GroupName, UserName=(grp==null)?"":grp.UserName};

var b=from u in Users
join g in Groups
on u.GroupId equals g.Id
into Grp
from grp in Grp.DefaultIfEmpty()
select new { GroupName=(grp==null)?"":grp.GroupName, UserName=u.UserName};

var c=a.Concat(b).Distinct();
c.Dump();

Lambda:
Groups
   .GroupJoin (
      Users, 
      g => (Int32?)(g.Id), 
      u => u.GroupId, 
      (g, Grp) => 
         new  
         {
            g = g, 
            Grp = Grp
         }
   )
   .SelectMany (
      temp0 => temp0.Grp.DefaultIfEmpty (), 
      (temp0, grp) => 
         new  
         {
            GroupName = temp0.g.GroupName, 
            UserName = (grp == null) ? "" : grp.UserName
         }
   )
   .Concat (
      Users
         .GroupJoin (
            Groups, 
            u => u.GroupId, 
            g => (Int32?)(g.Id), 
            (u, Grp) => 
               new  
               {
                  u = u, 
                  Grp = Grp
               }
         )
         .SelectMany (
            temp2 => temp2.Grp.DefaultIfEmpty (), 
            (temp2, grp) => 
               new  
               {
                  GroupName = (grp == null) ? "" : grp.GroupName, 
                  UserName = temp2.u.UserName
               }
         )
   )
   .Distinct ()

笛卡尔积、

Sql:
SELECT [t0].[GroupName], [t1].[UserName]
FROM [Group] AS [t0], [User] AS [t1]

Linq to Sql:
from g in Groups
from u in Users
select new { GroupName=g.GroupName, UserName=u.UserName}

Lambda:
Groups.SelectMany 
(
      g => Users, 
      (g, u) => 
         new  
         {
            GroupName = g.GroupName, 
            UserName = u.UserName
         }
   )

--------------------------------------------------------------------------------------------------------------------------------------------------------------

全连接(Full Outer Join),Linq并不支持,所以就需要使用其它方法来实现,就像不支持全连接的数据库一样,先使用内连接找出公共的部分,然后分别找出左连接和右连接的部分,把这三部分的结果UNION一下,即可得到全连接的效果。

看问题:

1
2
3
4
5
6
7
8
9
ID  FirstName
--  ---------
 1  John
 2  Sue
 
ID  LastName
--  --------
 1  Doe
 3  Smith
1
显示下面的结果:
1
2
3
4
5
ID  FirstName  LastName
--  ---------  --------
 1  John       Doe
 2  Sue
 3             Smith

实现方法一:

先找出左连接的结果,再找出右连接的结果,然后把这两个结果UNION即可,UNION时会自动把重复的数据过滤掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var firstNames = new[]
{
    new { ID = 1, Name = "John" },
    new { ID = 2, Name = "Sue" },
};
var lastNames = new[]
{
    new { ID = 1, Name = "Doe" },
    new { ID = 3, Name = "Smith" },
};
var leftOuterJoin = from first in firstNames
                    join last in lastNames
                    on first.ID equals last.ID
                    into temp
                    from last in temp.DefaultIfEmpty(new { first.ID, Name = default(string) })
                    select new
                    {
                        first.ID,
                        FirstName = first.Name,
                        LastName = last.Name,
                    };
var rightOuterJoin = from last in lastNames
                     join first in firstNames
                     on last.ID equals first.ID
                     into temp
                     from first in temp.DefaultIfEmpty(new { last.ID, Name = default(string) })
                     select new
                     {
                         last.ID,
                         FirstName = first.Name,
                         LastName = last.Name,
                     };
var fullOuterJoin = leftOuterJoin.Union(rightOuterJoin);

方法二:

得到左连接的数据,再从右连接的数据中把左连接的数据排除掉,两者的数据Concat一下即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var firstNames = new[]
{
    new { ID = 1, Name = "John" },
    new { ID = 2, Name = "Sue" },
};
var lastNames = new[]
{
    new { ID = 1, Name = "Doe" },
    new { ID = 3, Name = "Smith" },
};
var leftData = (from first in firstNames
                join last in lastNames on first.ID equals last.ID into temp
                from last in temp.DefaultIfEmpty(new { first.ID, Name = default(string) })
                select new
                {
                    first.ID,
                    FirstName = first.Name,
                    LastName = last.Name,
                });
 
var rightRemainingData = (from in lastNames
                          where !(from in leftData select a.ID).Contains(r.ID)
                          select new
                          {
                              r.ID,
                              FirstName = default(string),
                              LastName = r.Name
                          });
 
var fullOuterjoinData = leftData.Concat(rightRemainingData);

以上两种方法,其实是同一种方式来实现全连接的,只是第二次拿出的数据有所不同。

发表评论

0/200
83 点赞
0 评论
收藏