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


    转载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);

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

  • 相关阅读:
    为什么JSP的内置对象不需要声明
    什么不能输?
    可采用两种方法得到一个EJB对象
    EJB
    J2EE之JPA
    Application、Activity Stack 和 Task的区别
    关于 android屏幕适配
    JSP 向 JavaScript 中传递数组
    Android 图片异步加载 加载网络图片
    Android 显示意图和隐式意图的区别
  • 原文地址:https://www.cnblogs.com/johnblogs/p/6958392.html
Copyright © 2020-2023  润新知